home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Misc / msql-1.0.6 / src / msql / msqldb.c < prev    next >
C/C++ Source or Header  |  1995-05-28  |  102KB  |  5,428 lines

  1. /*
  2. **    msqldb.c    - 
  3. **
  4. **
  5. ** Copyright (c) 1993  David J. Hughes
  6. **
  7. ** Permission to use, copy, and distribute for non-commercial purposes,
  8. ** is hereby granted without fee, providing that the above copyright
  9. ** notice appear in all copies and that both the copyright notice and this
  10. ** permission notice appear in supporting documentation.
  11. **
  12. ** The software may be modified for your own purposes, but modified versions
  13. ** may not be distributed.
  14. **
  15. ** This software is provided "as is" without any expressed or implied warranty.
  16. **
  17. ** ID = "$Id:"
  18. **
  19. */
  20.  
  21.  
  22. /*
  23. ** Notes for people hacking on this code.
  24. **
  25. **    o A cache holding the details of the N most recently used tables
  26. **      is maintained.  Details include the table structure, FD's for
  27. **      the files on disk, pointers to mmap()ed if mmap() in use, a
  28. **      malloced area the size of a table row, and variaous other
  29. **      bits that are of use.  See cache_t in msql_priv.h for more
  30. **      info.  The size of the cache is also set there (must watch
  31. **      the number of entries as we can easily run out of FD's)
  32. **
  33. **    o The format of a row in a table is 
  34. **        <ActiveByte>[<NullByte><Value>]*
  35. **      The active byte will be 1 if the row is in use or 0 if it's a
  36. **      hole.  The null byte will be 1 if the value is NULL, 0
  37. **      otherwise.
  38. **
  39. **    o Given the above, a row starts at offset the combined length
  40. **      of all the fields + 1*number of fields + 1.
  41. */
  42.  
  43.  
  44.  
  45. #include <stdio.h>
  46. #include <fcntl.h>
  47. #include <unistd.h>
  48. #include <sys/types.h>
  49. #include <sys/stat.h>
  50. #include <sys/socket.h>
  51. #include <netinet/in.h>
  52. #include <arpa/inet.h>
  53. #include <signal.h>
  54. #include <netdb.h>
  55.  
  56.  
  57. #ifdef HAVE_MMAP
  58. #  include <sys/mman.h>
  59. #endif
  60.  
  61. #ifdef HAVE_DIRENT_H
  62. #  include <dirent.h>
  63. #endif
  64.  
  65. #ifdef HAVE_SYS_DIR_H
  66. #  include <sys/dir.h>
  67. #endif
  68.  
  69. #include <common/debug.h>
  70. #include <common/site.h>
  71. #include <common/portability.h>
  72. #include <regexp/regexp.h>
  73.  
  74. #include "y.tab.h"
  75.  
  76. #define    _MSQL_SERVER_SOURCE
  77.  
  78. #include "msql_priv.h"
  79. #include "msql.h"
  80. #include "errmsg.h"
  81.  
  82. #define NO_POS        0xFFFFFFFF
  83. #define    REG        register
  84.  
  85.  
  86. static    cache_t    tableCache[CACHE_SIZE];
  87.  
  88. extern    int    outSock;
  89. extern    char    *packet;
  90.  
  91. int    selectWildcard = 0,
  92.     selectDistinct = 0;
  93.  
  94. char    errMsg[200];
  95. char     readKeyBuf[BUF_SIZE];    /* Global to get it out of the stack frame */
  96. char    *msqlHomeDir;
  97.  
  98. char    *readRow();
  99. cache_t *loadTableDef();
  100.  
  101.  
  102. #define    MEM_ALLOC    1
  103. #define MEM_DEALLOC    2
  104. #define MEM_KILL_AGE    500
  105.  
  106. typedef struct _memBlock {
  107.     char    allocFile[40],
  108.         deallocFile[40];
  109.     int    allocLine,
  110.         deallocLine,
  111.         type,
  112.         status,
  113.         age;
  114.     caddr_t    addr;
  115.     off_t    size;
  116.     struct _memBlock *next;
  117. } memBlock;
  118.  
  119. static    memBlock *memHead = NULL;
  120.  
  121.  
  122.  
  123. pushBlock(file,line,type,addr,size)
  124.     char    *file;
  125.     int    line,
  126.         type;
  127.     caddr_t    addr;
  128.     off_t    size;
  129. {
  130.     memBlock *new;
  131.  
  132.     new = (memBlock *)malloc(sizeof(memBlock));
  133.     if (!new)
  134.     {
  135.         perror("malloc() :");
  136.         return;
  137.     }
  138.     (void)bzero(new,sizeof(memBlock));
  139.     (void)strcpy(new->allocFile,file);
  140.     new->allocLine = line;
  141.     new->type = type;
  142.     new->addr = addr;
  143.     new->size = size;
  144.     new->status = MEM_ALLOC;
  145.     if (memHead)
  146.     {
  147.         new->next = memHead;
  148.     }
  149.     else
  150.     {
  151.         new->next = NULL;
  152.     }
  153.     memHead = new;
  154. }
  155.  
  156.  
  157. dropBlock(file,line,addr,type)
  158.     char    *file;
  159.     int    line;
  160.     caddr_t    addr;
  161.     int    type;
  162. {
  163.     memBlock *cur,
  164.          *prev = NULL;
  165.     int    found = 0;
  166.  
  167.     cur = memHead;
  168.     while(cur)
  169.     {
  170.         if(cur->status == MEM_DEALLOC)
  171.         {
  172.             cur->age++;
  173.         }
  174.         if (cur->age > MEM_KILL_AGE)
  175.         {
  176.             if (prev)
  177.             {
  178.                 prev->next = cur->next;
  179.             }
  180.             else
  181.             {
  182.                 memHead = cur->next;
  183.             }
  184.             if (type == MMAP_BLK)
  185.             {
  186. #ifdef HAVE_MMAP
  187.                 munmap(cur->addr,cur->size);
  188. #endif
  189.             }
  190.             else
  191.             {
  192.                 free(cur->addr);
  193.             }
  194.             free(cur);
  195.         }
  196.         if (cur->addr == addr && cur->type == type)
  197.         {
  198.             if (cur->status == MEM_ALLOC)
  199.             {
  200.                 (void)strcpy(cur->deallocFile,file);
  201.                 cur->deallocLine = line;
  202.                 cur->status = MEM_DEALLOC;
  203.             }
  204.             else
  205.             {
  206.                 msqlDebug(0xffff,"Error: Muliple deallocation\n");
  207.                 msqlDebug(0xffff,"\t%u bytes at %X\n",
  208.                     cur->size, cur->addr);
  209.                 msqlDebug(0xffff,"\tAllocated at %s:%d\n",
  210.                     cur->allocFile, cur->allocLine);
  211.                 msqlDebug(0xffff,"\tDeallocated at %s:%d\n",
  212.                     cur->deallocFile, cur->deallocLine);
  213.                 abort();
  214.             }
  215.             found = 1;
  216.         }
  217.         prev = cur;
  218.         cur = cur->next;
  219.     }
  220.     if (!found)
  221.     {
  222.         msqlDebug(0xffff,"Error : drop of unknown memory block (%X)\n",
  223.             addr);
  224.     }
  225. }
  226.  
  227. checkBlocks(type)
  228.     int    type;
  229. {
  230.     memBlock *cur;
  231.     int    total,
  232.         count;
  233.  
  234.     cur = memHead;
  235.     total = count = 0;
  236.     while(cur)
  237.     {
  238.         if (cur->status == MEM_DEALLOC)
  239.         {
  240.             cur = cur->next;
  241.             continue;
  242.         }
  243.         total++;
  244.         if (cur->type == type)
  245.         {
  246.             count++;
  247.             msqlDebug(0xffff,"%s leak :-\n", blockTags[type]);
  248.             msqlDebug(0xffff,"\t%u bytes at %X\n",
  249.                 cur->size, cur->addr);
  250.             msqlDebug(0xffff,"\tBlock created at %s:%d\n\n",
  251.                 cur->allocFile, cur->allocLine);
  252.         }
  253.         cur = cur->next;
  254.     }
  255.     msqlDebug(0xffff,"Found %d leaked blocks of which %d where %s blocks\n",
  256.         total,count,blockTags[type]);
  257. }
  258.  
  259.  
  260.  
  261.  
  262. #ifdef HAVE_MMAP
  263.  
  264. caddr_t MMap(addr, len, prot, flags, fd, off,file,line)
  265.     caddr_t addr;
  266.     size_t len;
  267.     int prot, flags, fd;
  268.     off_t off;
  269.     char    *file;
  270.     int    line;
  271. {
  272.     caddr_t dest;
  273.  
  274.     dest = mmap(addr,len,prot,flags,fd,off);
  275.     msqlDebug(MOD_MMAP,"mmap'ing %u bytes at %X (%s:%d)\n",(unsigned)len,
  276.         dest,file,line);
  277.     if (dest == (caddr_t)-1)
  278.     {
  279.         perror("mmap");
  280.     }
  281.     if (debugSet(MOD_MMAP))
  282.         pushBlock(file,line,MMAP_BLK,dest,len);
  283.     return(dest);
  284. }
  285.  
  286. int MUnmap(addr,len,file,line)
  287.     caddr_t addr;
  288.     size_t len;
  289.     char    *file;
  290.     int    line;
  291. {
  292.     int    res = 0;
  293.  
  294.     msqlDebug(MOD_MMAP,"munmap'ing %u bytes from %X (%s:%d)\n",
  295.         (unsigned)len,addr, file, line);
  296.     if (debugSet(MOD_MMAP))
  297.         dropBlock(file,line,addr,MMAP_BLK);
  298.     else
  299.         res = munmap(addr,len);
  300.     if (res < 0)
  301.     {
  302.         perror("mmap");
  303.     }
  304.     return(res);
  305. }
  306.  
  307. #define mmap(a,l,p,fl,fd,o)    MMap(a,(size_t)l,p,fl,fd,o,__FILE__,__LINE__)
  308. #define munmap(a,l)         MUnmap(a,(size_t)l,__FILE__,__LINE__)
  309.  
  310.  
  311. #endif
  312.  
  313. char *Malloc(size,file,line)
  314.     int    size;
  315.     char    *file;
  316.     int    line;
  317. {
  318.     char    *cp;
  319.     REG    char *cp1;
  320.  
  321.     cp = (char *)malloc(size);
  322.     if (cp)
  323.     {
  324.         /*  An inline bzero() */
  325.         cp1 = cp;
  326.         while (cp1-cp < size)
  327.         {
  328.             *cp1++ = 0;
  329.         }
  330.         
  331.     }
  332.     msqlDebug(MOD_MALLOC,"Allocating %d bytes at %X (%s:%d)\n",size,cp,
  333.         file,line);
  334.     if (size > 1000000)
  335.     {
  336.         msqlDebug(MOD_MALLOC,"Huge malloc trapped!\n");
  337.         abort();
  338.     }
  339.     if (debugSet(MOD_MALLOC))
  340.         pushBlock(file,line,MALLOC_BLK,cp,size);
  341.     return(cp);
  342. }
  343.  
  344. void Free(addr, file,line)
  345.     char    *addr,
  346.         *file;
  347.     int    line;
  348. {
  349.     msqlDebug(MOD_MALLOC,"Freeing address %X (%s:%d)\n",addr,
  350.         file,line);
  351.     if (debugSet(MOD_MALLOC))
  352.         dropBlock(file,line,addr,MALLOC_BLK);
  353.     else
  354.         (void) free(addr);
  355. }
  356.  
  357.  
  358. #define malloc(s)        Malloc(s,__FILE__,__LINE__)
  359. #define free(a)            Free(a,__FILE__,__LINE__)
  360.  
  361. #define    safeFree(x)    {if(x) { (void)free(x); x = NULL; } }
  362.  
  363.  
  364.  
  365.  
  366. /****************************************************************************
  367. **     _openTable
  368. **
  369. **    Purpose    : Open the datafile for a given table
  370. **    Args    : Database and Table names
  371. **    Returns    : file descriptor for the data file
  372. **    Notes    : 
  373. */
  374.  
  375. int openTable(table,DB)
  376.     char    *table;
  377.     char    *DB;
  378. {
  379.     char    path[255];
  380.  
  381.     (void)sprintf(path,"%s/msqldb/%s/%s.dat",msqlHomeDir,DB,table);
  382.     return(open(path,O_RDWR));
  383. }
  384.  
  385.  
  386.  
  387. int openKey(table,DB)
  388.     char    *table;
  389.     char    *DB;
  390. {
  391.     char    path[255];
  392.  
  393.     (void)sprintf(path,"%s/msqldb/%s/%s.key",msqlHomeDir,DB,table);
  394.     return(open(path,O_RDWR));
  395. }
  396.  
  397.  
  398.  
  399.  
  400.  
  401. /****************************************************************************
  402. **     _openStack
  403. **
  404. **    Purpose    : Open the stack file for a given table
  405. **    Args    : Database and Table names
  406. **    Returns    : fiel descriptor of the stack file
  407. **    Notes    : 
  408. */
  409.  
  410. int openStack(table,DB)
  411.     char    *table;
  412.     char    *DB;
  413. {
  414.     char    path[255];
  415.  
  416.     (void)sprintf(path,"%s/msqldb/%s/%s.stk",msqlHomeDir,DB,table);
  417.     return(open(path,O_RDWR | O_CREAT, 0600));
  418. }
  419.  
  420.  
  421.  
  422.  
  423.  
  424. void initBackend()
  425. {
  426.     (void) bzero(tableCache, sizeof(tableCache));
  427. }
  428.  
  429.  
  430.  
  431.  
  432.  
  433. /****************************************************************************
  434. **     _popBlankPos
  435. **
  436. **    Purpose    : Pop the localtion of a hole from the table's file stack
  437. **    Args    : Database and table names
  438. **    Returns    : Offset off hole, NO_POS if the stack's empty
  439. **    Notes    : 
  440. */
  441.  
  442.  
  443. static u_int popBlankPos(cacheEntry,db,table)
  444.     cache_t    *cacheEntry;
  445.     char    *db,
  446.         *table;
  447. {
  448.     int    fd;
  449.     u_int    pos;
  450.     off_t    offset;
  451.  
  452.     msqlTrace(TRACE_IN,"popBlankPos()");
  453.     fd = cacheEntry->stackFD;
  454.     if (fd < 0)
  455.     {
  456.         msqlDebug(MOD_ACCESS,"popBlankPos() : No stack file for %s\n",
  457.             (cacheEntry->result)?cacheEntry->resInfo:
  458.             cacheEntry->table);
  459.         msqlTrace(TRACE_OUT,"popBlankPos()");
  460.         return(NO_POS);
  461.     }
  462.     offset = lseek(fd, (off_t) 0 - sizeof(int), SEEK_END);
  463.     if (offset < 0)
  464.     {
  465.         msqlDebug(MOD_ACCESS,"popBlankPos() : No hole in %s\n",
  466.             (cacheEntry->result)?cacheEntry->resInfo:
  467.             cacheEntry->table);
  468.         msqlTrace(TRACE_OUT,"popBlankPos()");
  469.         return(NO_POS);
  470.     }
  471.     read(fd,&pos,sizeof(u_int));
  472.     ftruncate(fd,offset);
  473.     msqlDebug(MOD_ACCESS,"popBlankPos() : Using hole at %u in %s\n",
  474.         pos,(cacheEntry->result)?cacheEntry->resInfo:cacheEntry->table);
  475.     msqlTrace(TRACE_OUT,"popBlankPos()");
  476.     return(pos);
  477. }
  478.  
  479.  
  480. /****************************************************************************
  481. **     _pushBlankPos
  482. **
  483. **    Purpose    : Store the location of a data hole 
  484. **    Args    : database and table names
  485. **          offset for the hole.
  486. **    Returns    : -1 on error
  487. **    Notes    : Using a stack-file for storage of the hole info
  488. **          enables a consistent and reliable access time for
  489. **          inserts into a table regardless of its size.
  490. */
  491.  
  492. static int pushBlankPos(cacheEntry,db,table,pos)
  493.     cache_t    *cacheEntry;
  494.     char    *db,
  495.         *table;
  496.     u_int    pos;
  497. {
  498.     int    fd;
  499.  
  500.     msqlTrace(TRACE_IN,"pushBlankPos()");
  501.     fd = cacheEntry->stackFD;
  502.     if (fd < 0)
  503.     {
  504.         msqlDebug(MOD_ACCESS,"pushBlankPos() : No stack file for %s\n",
  505.         (cacheEntry->result)?cacheEntry->resInfo:cacheEntry->table);
  506.         msqlTrace(TRACE_OUT,"pushBlankPos()");
  507.         return(-1);
  508.     }
  509.     lseek(fd, (off_t) 0, SEEK_END);
  510.     write(fd,&pos,sizeof(u_int));
  511.     msqlDebug(MOD_ACCESS,"pushBlankPos() : Setting hole at %u in %s\n",
  512.         pos,(cacheEntry->result)?cacheEntry->resInfo:cacheEntry->table);
  513.     msqlTrace(TRACE_OUT,"pushBlankPos()");
  514.     return(0);
  515. }
  516.  
  517.  
  518.  
  519. static void setupKey(cacheEntry,key)
  520.     cache_t    *cacheEntry;
  521.     pkey_t     *key;
  522. {
  523.     val_t    value;
  524.  
  525.     msqlTrace(TRACE_IN,"setupKey()");
  526.     bzero(cacheEntry->keyBuf,cacheEntry->keyLen+1);
  527.     value = *(key->value);
  528.     switch(key->value->type)
  529.     {
  530.         case INT_TYPE:
  531. #ifndef _CRAY
  532.             bcopy(&value.val.intVal,
  533.                 cacheEntry->keyBuf+1,cacheEntry->keyLen);
  534. #else
  535.             packInt32(value.val.intVal, cacheEntry->keyBuf+1);
  536. #endif
  537.             break;
  538.         
  539.         case CHAR_TYPE:
  540.             bcopy(value.val.charVal, cacheEntry->keyBuf+1,
  541.                 strlen(value.val.charVal));
  542.             break;
  543.  
  544.         case REAL_TYPE:
  545.             bcopy(&value.val.realVal,
  546.                 cacheEntry->keyBuf+1,cacheEntry->keyLen);
  547.             break;
  548.     }
  549.     msqlTrace(TRACE_OUT,"setupKey()");
  550. }
  551.  
  552.  
  553.  
  554.  
  555. /****************************************************************************
  556. **     _msqlListDBs
  557. **
  558. **    Purpose    : Send a list of available databases to the client
  559. **    Args    : Client socket
  560. **    Returns    : -1 on error
  561. **    Notes    : The only things in the top level data directory are
  562. **          database directories so we just send a file listing.
  563. */
  564.  
  565. int msqlListDBs(sock)
  566.     int    sock;
  567. {
  568.     char    path[255];
  569.     DIR    *dirp;
  570. #ifdef HAVE_DIRENT
  571.     struct    dirent *cur;
  572. #else
  573.     struct    direct *cur;
  574. #endif
  575.  
  576.     msqlTrace(TRACE_IN,"msqlListDBs()");
  577.     (void)sprintf(path,"%s/msqldb",msqlHomeDir);
  578.     dirp = opendir(path);
  579.     if (!dirp)
  580.     {
  581.         sprintf(errMsg,BAD_DIR_ERROR,path);
  582.         msqlDebug(MOD_ERR,"Can't open directory \"%s\"\n",path);
  583.         msqlTrace(TRACE_OUT,"msqlListDBs()");
  584.         return(-1);
  585.     }
  586.     
  587.     /*
  588.     ** Grab the names dodging any . files
  589.     */
  590.  
  591.     cur = readdir(dirp);
  592.     while(cur)
  593.     {
  594.         if (*cur->d_name == '.')
  595.         {
  596.             cur = readdir(dirp);
  597.             continue;
  598.         }
  599.         sprintf(packet,"%d:%s\n",strlen(cur->d_name),cur->d_name);
  600.         writePkt(sock);
  601.         cur = readdir(dirp);
  602.     }
  603.     sprintf(packet,"-100:\n");
  604.     writePkt(sock);
  605.     closedir(dirp);
  606.     msqlTrace(TRACE_OUT,"msqlListDBs()");
  607.     return(0);
  608. }
  609.  
  610.  
  611.  
  612.  
  613.  
  614.  
  615. /****************************************************************************
  616. **     _msqlListTables
  617. **
  618. **    Purpose    : Send a list of available tables for a given DB
  619. **    Args    : Client socket and Database name
  620. **    Returns    : -1 on error
  621. **    Notes    : Looks for table definitions files (*.def)
  622. */
  623.  
  624. int msqlListTables(sock,DB)
  625.     int    sock;
  626.     char    *DB;
  627. {
  628.     char    path[255],
  629.         *cp;
  630.     DIR    *dirp;
  631. #ifdef HAVE_DIRENT
  632.     struct    dirent *cur;
  633. #else
  634.     struct    direct *cur;
  635. #endif
  636.  
  637.     msqlTrace(TRACE_IN,"msqlListTables()");
  638.     (void)sprintf(path,"%s/msqldb/%s",msqlHomeDir,DB);
  639.     dirp = opendir(path);
  640.     if (!dirp)
  641.     {
  642.         sprintf(errMsg,BAD_DIR_ERROR,path);
  643.         msqlDebug(MOD_ERR,"Can't open directory \"%s\"\n",path);
  644.         msqlTrace(TRACE_OUT,"msqlListTables()");
  645.         return(-1);
  646.     }
  647.     
  648.     /*
  649.     ** Skip over '.' and '..'
  650.     */
  651.     cur = readdir(dirp);
  652.     while(cur)
  653.     {
  654.         if (*cur->d_name != '.')
  655.             break;
  656.         cur = readdir(dirp);
  657.     }
  658.  
  659.     /*
  660.     ** Grab the names
  661.     */
  662.  
  663.     while(cur)
  664.     {
  665.         cp = (char *)rindex(cur->d_name,'.');
  666.         if (!cp)
  667.         {
  668.             cur = readdir(dirp);
  669.             continue;
  670.         }
  671.     
  672.         if (strcmp(cp,".def") == 0)
  673.         {
  674.             *cp = 0;
  675.             sprintf(packet,"%d:%s\n",
  676.                 strlen(cur->d_name),cur->d_name);
  677.             writePkt(sock);
  678.         }
  679.         cur = readdir(dirp);
  680.     }
  681.     sprintf(packet,"-100:\n");
  682.     writePkt(sock);
  683.     closedir(dirp);
  684.     msqlTrace(TRACE_OUT,"msqlListTables()");
  685.     return(0);
  686. }
  687.  
  688.  
  689.  
  690.  
  691.  
  692.  
  693. /****************************************************************************
  694. **     _msqlListFields
  695. **
  696. **    Purpose    : Send a list of table fields to the client
  697. **    Args    : Client socket.  Table and database names
  698. **    Returns    : 
  699. **    Notes    : 
  700. */
  701.  
  702. void msqlListFields(sock,table,DB)
  703.     int    sock;
  704.     char    *table,
  705.         *DB;
  706. {
  707.      field_t    *curField;
  708.     char    buf[50];
  709.     cache_t    *cacheEntry;
  710.  
  711.     msqlTrace(TRACE_IN,"msqlListFields()");
  712.     msqlDebug(MOD_GENERAL,"Table to list = %s\n",table);
  713.     if((cacheEntry = loadTableDef(table,NULL,DB)))
  714.     {
  715.               curField = cacheEntry->def;
  716.         while(curField)
  717.         {
  718.             sprintf(buf,"%d",curField->length);
  719.             sprintf(packet,"%d:%s%d:%s1:%d%d:%s1:%s1:%s", 
  720.                 strlen(table), table,
  721.                 strlen(curField->name), curField->name, 
  722.                 curField->type,strlen(buf), buf, 
  723.                 curField->flags & NOT_NULL_FLAG?"Y":"N", 
  724.                 curField->flags & PRI_KEY_FLAG ?"Y":"N");
  725.             writePkt(sock);
  726.             curField = curField->next;
  727.         }
  728.     }
  729.     sprintf(packet,"-100:\n");
  730.     writePkt(sock);
  731.     msqlTrace(TRACE_OUT,"msqlListFields()");
  732. }
  733.  
  734.  
  735.  
  736.  
  737.  
  738.  
  739. /****************************************************************************
  740. **     _msqlBackendInit
  741. **
  742. **    Purpose    : Any db backend startup code - called per query
  743. **    Args    : None
  744. **    Returns    : Nothing
  745. **    Notes    : 
  746. */
  747.  
  748. void msqlBackendInit()
  749. {
  750.     (void)bzero(tableCache,sizeof(tableCache));
  751. }
  752.  
  753.  
  754.  
  755.  
  756.  
  757. /****************************************************************************
  758. **     _msqlBackendClean
  759. **
  760. **    Purpose    : Any db cleanup code - called after query processed
  761. **    Args    : None
  762. **    Returns    : Nothing
  763. **    Notes    : 
  764. */
  765.  
  766. void msqlBackendClean()
  767. {
  768.     selectWildcard = 0;
  769.     selectDistinct = 0;
  770. }
  771.  
  772.  
  773.  
  774.  
  775.  
  776.  
  777.  
  778. /****************************************************************************
  779. **     _freeTableDef
  780. **
  781. **    Purpose    : Free memory used by a table def
  782. **    Args    : pointer to table def
  783. **    Returns    : Nothing
  784. **    Notes    : 
  785. */
  786.  
  787. static void freeTableDef(tableDef)
  788.     field_t    *tableDef;
  789. {
  790.     field_t    *curField,
  791.         *prevField;
  792.  
  793.     msqlTrace(TRACE_IN,"freeTableDef()");
  794.     curField = tableDef;
  795.     while(curField)
  796.     {
  797.         prevField = curField;
  798.         curField = curField->next;
  799.  
  800.         safeFree(prevField);
  801.     }
  802.     msqlTrace(TRACE_OUT,"freeTableDef()");
  803. }
  804.  
  805.  
  806. static void freeCacheEntry(entry)
  807.     cache_t    *entry;
  808. {
  809.     msqlTrace(TRACE_IN,"freeCacheEntry()");
  810.     freeTableDef(entry->def);
  811.     entry->def = NULL;
  812.     *(entry->DB) = 0;
  813.     *(entry->table) = 0;
  814.     entry->age = 0;
  815.     safeFree(entry->rowBuf);
  816.     safeFree(entry->keyBuf);
  817. #ifdef HAVE_MMAP
  818.     if (entry->dataMap != (caddr_t) NULL)
  819.     {
  820.         munmap(entry->dataMap,entry->size);
  821.         entry->dataMap = NULL;
  822.         entry->size = 0;
  823.     }
  824.     if (entry->keyMap != (caddr_t) NULL)
  825.     {
  826.         munmap(entry->keyMap,entry->keySize);
  827.         entry->keyMap = NULL;
  828.         entry->keySize = 0;
  829.     }
  830. #endif
  831.     close(entry->stackFD);
  832.     close(entry->dataFD);
  833.     close(entry->keyFD);
  834.     msqlTrace(TRACE_OUT,"freeCacheEntry()");
  835. }
  836.  
  837.  
  838.  
  839. void dropCache()
  840. {
  841.     int    index = 0;
  842.  
  843.     while(index < CACHE_SIZE)
  844.     {
  845.         if (tableCache[index].def)
  846.         {
  847.             freeCacheEntry(tableCache + index);
  848.         }
  849.         index++;
  850.     }
  851. }
  852.  
  853. /****************************************************************************
  854. **     _readTableDef
  855. **
  856. **    Purpose    : Load a table definition from file
  857. **    Args    : Database and Table names
  858. **    Returns    : pointer to table definition
  859. **    Notes    : 
  860. */
  861.  
  862. field_t *readTableDef(table,alias,DB,keyLen)
  863.     char    *table,
  864.         *alias,
  865.         *DB;
  866.     int    *keyLen;
  867. {
  868.     field_t    *headField,
  869.         *tmpField,
  870.         *prevField,
  871.         *curField;
  872.     char    path[255];
  873.     int    numFields,
  874.         numBytes,
  875.         fieldCount,
  876.         fd;
  877.     static    char buf[MAX_FIELDS * sizeof(field_t)];
  878.  
  879.     msqlTrace(TRACE_IN,"readTableDef()");
  880.     (void)sprintf(path,"%s/msqldb/%s/%s.def",msqlHomeDir,DB,table);
  881.     fd = open(path,O_RDONLY,0);
  882.     if (fd < 0)
  883.     {
  884.         sprintf(errMsg,BAD_TABLE_ERROR,table);
  885.         msqlDebug(MOD_ERR,"Unknown table \"%s\"\n",table);
  886.         msqlTrace(TRACE_OUT,"readTableDef()");
  887.         return(NULL);
  888.     }
  889.     numBytes = read(fd,buf,sizeof(buf));
  890.     if (numBytes < 1)
  891.     {
  892.         sprintf(errMsg,TABLE_READ_ERROR,table);
  893.         msqlDebug(MOD_ERR,"Error reading table \"%s\" definition\n",table);
  894.         msqlTrace(TRACE_OUT,"readTableDef()");
  895.         return(NULL);
  896.     }
  897.         
  898.     numFields = numBytes / sizeof(field_t);
  899.     fieldCount = 0;
  900.     *keyLen = 0;
  901.     headField = NULL;
  902.     while(fieldCount < numFields)
  903.     {
  904.         tmpField = (field_t *)(buf + (fieldCount * sizeof(field_t)));
  905.         curField = (field_t *)malloc(sizeof(field_t));
  906.         if (!headField)
  907.         {
  908.             headField = prevField = curField;
  909.         }
  910.         else
  911.         {
  912.             prevField->next = curField;
  913.             prevField = curField;
  914.         }
  915.         (void)bcopy(tmpField, curField, sizeof(field_t));
  916.         if (alias)
  917.         {
  918.             strcpy(curField->table,alias);
  919.         }
  920.         if (tmpField->flags & PRI_KEY_FLAG)
  921.         {
  922.             *keyLen = tmpField->length;
  923.         }
  924.         fieldCount++;
  925.     }
  926.     close(fd);
  927.     msqlTrace(TRACE_OUT,"readTableDef()");
  928.     return(headField);
  929. }
  930.  
  931.  
  932.  
  933.  
  934.  
  935.  
  936. static cache_t *createTmpTable(table1,table2,fields)
  937.     cache_t    *table1,
  938.         *table2;
  939.     field_t    *fields;
  940. {
  941.     REG    cache_t *new;
  942.     field_t    *curField,
  943.         *newField,
  944.         *tmpField;
  945.     char    path[255],
  946.         *tmpfile,
  947.         *cp;
  948.     int    fd,
  949.         foundField;
  950.  
  951.  
  952.     /*
  953.     ** Create a name for this tmp table
  954.     */
  955.     msqlTrace(TRACE_IN,"createTmpTable()");
  956.     tmpfile = (char *)tmpnam(NULL);
  957.     cp = (char *)rindex(tmpfile,'/');
  958.     if (cp)
  959.     {
  960.         tmpfile = cp+1;
  961.     }
  962.     (void)sprintf(path,"%s/msqldb/.tmp/%s.dat",msqlHomeDir,tmpfile);
  963.     (void)sprintf(path,"/tmp/%s.dat",tmpfile);
  964.  
  965.  
  966.     /*
  967.     ** start building the table cache entry
  968.     */
  969.     new = (cache_t *)malloc(sizeof(cache_t));
  970.     if (!new)
  971.     {
  972.         sprintf(errMsg,TMP_MEM_ERROR);
  973.         msqlDebug(MOD_ERR,"Out of memory for temporary table (%s)\n"
  974.         ,path);
  975.         msqlTrace(TRACE_OUT,"createTmpTable()");
  976.         return(NULL);
  977.     }
  978.     (void)strcpy(new->table,tmpfile);
  979.     fd = open(path,O_RDWR|O_CREAT|O_TRUNC, 0700);
  980.     if (fd < 0)
  981.     {
  982.         sprintf(errMsg,TMP_CREATE_ERROR);
  983.         msqlDebug(MOD_ERR,"Couldn't create temporary table (%s)\n",
  984.             path);
  985.         (void)free(new);
  986.         msqlTrace(TRACE_OUT,"createTmpTable()");
  987.         return(NULL);
  988.     }
  989.     new->dataFD = fd;
  990.     new->keyFD = new->stackFD = -1;
  991.     new->result = 1;
  992.  
  993.  
  994.     /*
  995.     ** Add the field definitions.  Ensure that any key fields are
  996.     ** not flagged as such as we can't access the key data of the
  997.     ** original table when accessing this.
  998.     */
  999.  
  1000.     curField = table1->def;
  1001.     newField = NULL;
  1002.     while(curField)
  1003.     {
  1004.         /*
  1005.         ** If we've been given a list of fields, only add this
  1006.         ** field to the tmp table if it's in the list.
  1007.         */
  1008.         if (fields)
  1009.         {
  1010.             foundField = 0;
  1011.             tmpField = fields;
  1012.             while(tmpField)
  1013.             {
  1014.                 if(strcmp(tmpField->name,curField->name)==0 &&
  1015.                    strcmp(tmpField->table,curField->table)==0)
  1016.                 {
  1017.                     foundField = 1;
  1018.                     break;
  1019.                 }
  1020.                 tmpField = tmpField->next;
  1021.             }
  1022.             if (!foundField)
  1023.             {
  1024.                 curField = curField->next;
  1025.                 continue;
  1026.             }
  1027.         }
  1028.  
  1029.         /*
  1030.         ** O.k.  Add this field
  1031.         */
  1032.         if (newField)
  1033.         {
  1034.             newField->next = (field_t *)malloc(sizeof(field_t));
  1035.             newField = newField->next;
  1036.         }
  1037.         else
  1038.         {
  1039.             new->def=newField=(field_t *)malloc(sizeof(field_t));
  1040.         }
  1041.         (void)bcopy(curField,newField,sizeof(field_t));
  1042.         if( *(newField->table) == 0)
  1043.         {
  1044.             (void)strcpy(newField->table,table1->table);
  1045.         }
  1046.         newField->flags=0;
  1047.         new->rowLen += curField->length + 1;
  1048.         curField = curField->next;
  1049.     }
  1050.     if (table2)
  1051.     {
  1052.         curField = table2->def;
  1053.         while(curField)
  1054.         {
  1055.             /*
  1056.             ** If we've been given a list of fields, only add this
  1057.             ** field to the tmp table if it's in the list.
  1058.             */
  1059.             if (fields)
  1060.             {
  1061.                 foundField = 0;
  1062.                 tmpField = fields;
  1063.                 while(tmpField)
  1064.                 {
  1065.                     if(strcmp(tmpField->name,
  1066.                         curField->name)==0 &&
  1067.                        strcmp(tmpField->table,
  1068.                         curField->table)==0)
  1069.                     {
  1070.                         foundField = 1;
  1071.                         break;
  1072.                     }
  1073.                     tmpField = tmpField->next;
  1074.                 }
  1075.                 if (!foundField)
  1076.                 {
  1077.                     curField = curField->next;
  1078.                     continue;
  1079.                 }
  1080.             }
  1081.  
  1082.             /*
  1083.             ** Add it.
  1084.             */
  1085.             if (newField)
  1086.             {
  1087.                 newField->next = (field_t *)malloc(
  1088.                     sizeof(field_t));
  1089.                 newField = newField->next;
  1090.             }
  1091.             else
  1092.             {
  1093.                 new->def=newField=(field_t *)malloc(
  1094.                     sizeof(field_t));
  1095.             }
  1096.             (void)bcopy(curField,newField,sizeof(field_t));
  1097.             if( *(newField->table) == 0)
  1098.             {
  1099.                 (void)strcpy(newField->table,table2->table);
  1100.             }
  1101.             new->rowLen += curField->length + 1;
  1102.             curField = curField->next;
  1103.         }
  1104.     }
  1105.  
  1106.     if (newField)    
  1107.     {
  1108.         newField->next = NULL;
  1109.     }
  1110.     new->rowBuf = (u_char *)malloc(new->rowLen+1);
  1111.     new->keyLen = 0;
  1112.     msqlTrace(TRACE_OUT,"createTmpTable()");
  1113.     return(new);
  1114. }
  1115.  
  1116.  
  1117.  
  1118.  
  1119. static void freeTmpTable(entry)
  1120.     cache_t    *entry;
  1121. {
  1122.     char    path[255];
  1123.  
  1124.         msqlTrace(TRACE_IN,"freeTmpTable()");
  1125.     (void)sprintf(path,"%s/msqldb/.tmp/%s.dat",msqlHomeDir,entry->table);
  1126.     (void)sprintf(path,"/tmp/%s.dat",entry->table);
  1127.     freeTableDef(entry->def);
  1128.     entry->def = NULL;
  1129.     *(entry->DB) = 0;
  1130.     *(entry->table) = 0;
  1131.     entry->age = 0;
  1132.     safeFree(entry->rowBuf);
  1133.     safeFree(entry->keyBuf);
  1134. #ifdef HAVE_MMAP
  1135.     if (entry->dataMap != (caddr_t) NULL)
  1136.     {
  1137.         munmap(entry->dataMap,entry->size);
  1138.         entry->dataMap = NULL;
  1139.         entry->size = 0;
  1140.     }
  1141.     if (entry->keyMap != (caddr_t) NULL)
  1142.     {
  1143.         munmap(entry->keyMap,entry->keySize);
  1144.         entry->keyMap = NULL;
  1145.         entry->keySize = 0;
  1146.     }
  1147. #endif
  1148.     close(entry->stackFD);
  1149.     close(entry->dataFD);
  1150.     close(entry->keyFD);
  1151.     (void)free(entry);
  1152.     unlink(path);
  1153.         msqlTrace(TRACE_OUT,"freeTmpTable()");
  1154. }
  1155.  
  1156.  
  1157.  
  1158. /****************************************************************************
  1159. **     _findRowLen
  1160. **
  1161. **    Purpose    : Determine the on-disk size of a table's rows
  1162. **    Args    : None
  1163. **    Returns    : Row Length
  1164. **    Notes    : Uses global table definition pointer.
  1165. */
  1166.  
  1167. static int findRowLen(cacheEntry)
  1168.     cache_t    *cacheEntry;
  1169. {
  1170.     int    rowLen;
  1171.     field_t    *fieldDef;
  1172.  
  1173.     rowLen = 0;
  1174.     fieldDef = cacheEntry->def;
  1175.     while(fieldDef)
  1176.     {
  1177.         rowLen += fieldDef->length +1;  /* +1 for NULL indicator */
  1178.         fieldDef = fieldDef->next;
  1179.     }
  1180.     return(rowLen);
  1181. }
  1182.  
  1183.  
  1184.  
  1185.  
  1186. /****************************************************************************
  1187. **     _loadTableDef
  1188. **
  1189. **    Purpose    : Locate a table definition
  1190. **    Args    : Database and Table names
  1191. **    Returns    : -1 on error
  1192. **    Notes    : Table description cache searched first.  If it's not
  1193. **          there, the LRU entry is freed and the table def is
  1194. **          loaded into the cache.  The tableDef, stackFD,
  1195. **          cacheEntry and dataFD globals are set.
  1196. */
  1197.  
  1198.  
  1199. cache_t *loadTableDef(table,cname,DB)
  1200.     char    *table,
  1201.         *cname,
  1202.         *DB;
  1203. {
  1204.     int    maxAge,
  1205.         cacheIndex,
  1206.         keyLen;
  1207.     field_t    *def;
  1208.     REG     cache_t    *entry;
  1209.     REG     int    count;
  1210.     char    path[255],
  1211.         *tableName;
  1212.  
  1213.  
  1214.     /*
  1215.     ** Look for the entry in the cache.  Keep track of the oldest
  1216.     ** entry during the pass so that we can replace it if needed
  1217.     */
  1218.     msqlTrace(TRACE_IN,"loadTableDef()");
  1219.     msqlDebug(MOD_CACHE,"Table cache search for %s:%s\n",table,DB);
  1220.     count = cacheIndex = 0;
  1221.     maxAge = -1;
  1222.     if (cname)
  1223.     {
  1224.         if (!*cname)
  1225.         {
  1226.             cname = NULL;
  1227.         }
  1228.     }
  1229.     while(count < CACHE_SIZE)
  1230.     {
  1231.         entry = tableCache + count;
  1232.         msqlDebug(MOD_CACHE,"Cache entry %d = %s:%s, age = %d\n", count,
  1233.             entry->table?entry->table:"NULL",
  1234.             entry->DB?entry->DB:"NULL", 
  1235.             entry->age);
  1236.         if (strcmp(entry->DB,DB)==0 && strcmp(entry->table,table)==0 &&
  1237.             strcmp((cname)?cname:"",entry->cname)==0)
  1238.         {
  1239.             msqlDebug(MOD_CACHE,"Found cache entry at %d\n", count);
  1240.             entry->age = 1;
  1241.             msqlTrace(TRACE_OUT,"loadTableDef()");
  1242.             return(entry);
  1243.         }
  1244.         if (entry->age > 0)
  1245.             entry->age++;
  1246.  
  1247.         /*
  1248.         ** Empty entries have an age of 0.  If we're marking
  1249.         ** an empty cache position just keep the mark
  1250.         */
  1251.         if ((entry->age == 0) && (maxAge != 0))
  1252.         {
  1253.             maxAge = entry->age;
  1254.             cacheIndex = count;
  1255.         }
  1256.         else
  1257.         {
  1258.             if ((entry->age > maxAge) && (maxAge != 0))
  1259.             {
  1260.                 maxAge = entry->age;
  1261.                 cacheIndex = count;
  1262.             }
  1263.         }
  1264.         count++;
  1265.     }
  1266.  
  1267.     /*
  1268.     ** It wasn't in the cache.  Free up the oldest cache entry 
  1269.     */
  1270.  
  1271.     entry = tableCache + cacheIndex;
  1272.     if(entry->def)
  1273.     {
  1274.         msqlDebug(MOD_CACHE,"Removing cache entry %d (%s:%s)\n", 
  1275.             cacheIndex, entry->DB, entry->table);
  1276. #ifdef HAVE_MMAP
  1277.         if (entry->dataMap != (caddr_t) NULL)
  1278.         {
  1279.             munmap(entry->dataMap,entry->size);
  1280.             entry->dataMap = NULL;
  1281.             entry->size = 0;
  1282.         }
  1283.         if (entry->keyMap != (caddr_t) NULL)
  1284.         {
  1285.             munmap(entry->keyMap,entry->keySize);
  1286.             entry->keyMap = NULL;
  1287.             entry->keySize = 0;
  1288.         }
  1289. #endif
  1290.         (void)close(entry->stackFD);
  1291.         (void)close(entry->dataFD);
  1292.         (void)close(entry->keyFD);
  1293.         freeTableDef(entry->def);
  1294.         safeFree(entry->rowBuf);
  1295.         safeFree(entry->keyBuf);
  1296.         entry->def = NULL;
  1297.     }
  1298.  
  1299.     /*
  1300.     ** Now load the new entry
  1301.     */
  1302.     if (cname)
  1303.     {
  1304.         tableName = cname;
  1305.         def = readTableDef(cname,table,DB,&keyLen);
  1306.     }
  1307.     else
  1308.     {
  1309.         tableName = table;
  1310.         def = readTableDef(table,NULL,DB,&keyLen);
  1311.     }
  1312.     if (!def)
  1313.     {
  1314.         sprintf(errMsg,TABLE_READ_ERROR,table);
  1315.         msqlDebug(MOD_ERR,"Couldn't read table definition for %s\n",table);
  1316.         msqlTrace(TRACE_OUT,"loadTableDef()");
  1317.         return(NULL);
  1318.     }
  1319.     entry->def = def;
  1320.     entry->age = 1;
  1321.     entry->result = 0;
  1322.     entry->keyLen = keyLen;
  1323.     strcpy(entry->DB,DB);
  1324.     strcpy(entry->table,table);
  1325.     if (cname)
  1326.     {
  1327.         strcpy(entry->cname,cname);
  1328.     }
  1329.     
  1330.     msqlDebug(MOD_CACHE,"Loading cache entry %d (%s:%s)\n", cacheIndex, 
  1331.         entry->DB, entry->table);
  1332.     if((entry->dataFD = openTable(tableName,DB)) < 0)
  1333.     {
  1334.         sprintf(errMsg,DATA_OPEN_ERROR,tableName);
  1335.         msqlTrace(TRACE_OUT,"loadTableDef()");
  1336.         return(NULL);
  1337.     }
  1338.     if((entry->stackFD = openStack(tableName,DB)) < 0)
  1339.     {
  1340.         sprintf(errMsg,STACK_OPEN_ERROR,tableName);
  1341.         msqlTrace(TRACE_OUT,"loadTableDef()");
  1342.         return(NULL);
  1343.     }
  1344.     entry->keyFD = openKey(tableName,DB);
  1345.  
  1346. #ifdef HAVE_MMAP
  1347.     /*
  1348.     ** Setup for Mapping the data file
  1349.     */
  1350.     entry->dataMap = NULL;
  1351.     entry->keyMap = NULL;
  1352.     entry->remapData = 1;
  1353.     if (entry->keyFD == -1)
  1354.         entry->remapKey = 0;
  1355.     else
  1356.         entry->remapKey = 1;
  1357.     initTable(entry,FULL_REMAP);
  1358. #endif
  1359.  
  1360.     /*
  1361.     ** Set the globals and bail.  We need rowLen + 2 (one for the
  1362.     ** active byte and also one for regexp over-run protection) and
  1363.     ** keyLen + 1 (one for the active byte) buffers for performance.
  1364.     */
  1365.     entry->rowLen = findRowLen(entry);
  1366.     entry->rowBuf = (u_char *)malloc(entry->rowLen + 2);
  1367.     entry->keyBuf = (u_char *)malloc(entry->keyLen + 1);
  1368.     msqlTrace(TRACE_OUT,"loadTableDef()");
  1369.     return(entry);
  1370. }
  1371.  
  1372.  
  1373.  
  1374.  
  1375.  
  1376.  
  1377.  
  1378. /****************************************************************************
  1379. **     _initTable
  1380. **
  1381. **    Purpose    : Reset table pointers used during query processing
  1382. **    Args    : None
  1383. **    Returns    : Nothing
  1384. **    Notes    : This just puts the file into a known state, particular
  1385. **          the current seek pointers.
  1386. */
  1387.  
  1388. int initTable(cacheEntry,mapFlag)
  1389.     cache_t    *cacheEntry;
  1390.     int    mapFlag;
  1391. {
  1392.     struct    stat sbuf;
  1393.     char    active;
  1394.  
  1395.     msqlTrace(TRACE_IN,"initTable()");
  1396. #ifdef HAVE_MMAP
  1397.     if (mapFlag && FULL_REMAP)
  1398.     {
  1399.         if (cacheEntry->remapData)
  1400.         {
  1401.             if (cacheEntry->dataMap != (caddr_t) NULL &&
  1402.                 cacheEntry->dataMap != (caddr_t) -1 )
  1403.             {
  1404.                         munmap(cacheEntry->dataMap, cacheEntry->size);
  1405.             }
  1406.             fstat(cacheEntry->dataFD, &sbuf);
  1407.             cacheEntry->size = sbuf.st_size;
  1408.             if (cacheEntry->size)
  1409.             {
  1410.                 cacheEntry->dataMap = (caddr_t)mmap(NULL, 
  1411.                     cacheEntry->size, 
  1412.                     (PROT_READ | PROT_WRITE), 
  1413.                     MAP_SHARED, cacheEntry->dataFD, 0);
  1414.                 if (cacheEntry->dataMap == (caddr_t)-1)
  1415.                     return(-1);
  1416.             }
  1417.             cacheEntry->remapData = 0;
  1418.         }
  1419.     }
  1420.     if (mapFlag && FULL_REMAP || mapFlag && KEY_REMAP)
  1421.     {
  1422.         if (cacheEntry->remapKey)
  1423.         {
  1424.             if (cacheEntry->keyMap)
  1425.             {
  1426.                            munmap(cacheEntry->keyMap, 
  1427.                     cacheEntry->keySize);
  1428.             }
  1429.             fstat(cacheEntry->keyFD, &sbuf);
  1430.             cacheEntry->keySize = sbuf.st_size;
  1431.             if (cacheEntry->keySize)
  1432.             {
  1433.                 cacheEntry->keyMap = (caddr_t) mmap(NULL, 
  1434.                     cacheEntry->keySize,
  1435.                     PROT_READ | PROT_WRITE, MAP_SHARED, 
  1436.                     cacheEntry->keyFD, 0);
  1437.                 if (cacheEntry->keyMap == (caddr_t)-1)
  1438.                     return(-1);
  1439.             }
  1440.             cacheEntry->remapKey = 0;
  1441.         }
  1442.     }
  1443. #else
  1444.     readRow(cacheEntry,&active,NO_POS);
  1445. #endif
  1446.     msqlTrace(TRACE_OUT,"initTable()");
  1447.     return(0);
  1448. }
  1449.  
  1450.     
  1451.  
  1452.  
  1453.  
  1454.  
  1455. /****************************************************************************
  1456. **     _writeRow
  1457. **
  1458. **    Purpose    : Store a table row in the database
  1459. **    Args    : datafile FD, row data, length of data, target offset
  1460. **    Returns    : -1 on error
  1461. **    Notes    : If the rowNum is NO_POS then append the row
  1462. */
  1463.  
  1464. #ifdef HAVE_MMAP
  1465.  
  1466. int writeRow(cacheEntry,row,rowNum)
  1467.     cache_t    *cacheEntry;
  1468.     char    *row;
  1469.     u_int    rowNum;
  1470. {
  1471.     char    active = 1;
  1472.     REG    off_t    seekPos;
  1473.     char    *buf;
  1474.  
  1475.  
  1476.     if (rowNum == NO_POS)
  1477.     {
  1478.         msqlDebug(MOD_ACCESS,"writeRow() : append to %s\n",
  1479.             (cacheEntry->result)?cacheEntry->resInfo:
  1480.             cacheEntry->table);
  1481.     }
  1482.     else
  1483.     {
  1484.         msqlDebug(MOD_ACCESS,"writeRow() : write at row %u of %s\n",
  1485.             rowNum, (cacheEntry->result)?cacheEntry->resInfo:
  1486.             cacheEntry->table);
  1487.     }
  1488.     *cacheEntry->rowBuf = (u_char) active;
  1489.     if (rowNum == NO_POS)  /* append and flag remap */
  1490.     {
  1491.         cacheEntry->remapData = 1;
  1492.         lseek(cacheEntry->dataFD,(off_t)0, SEEK_END);
  1493.         if (row)
  1494.         {
  1495.             bcopy(cacheEntry->rowBuf+1,row,cacheEntry->rowLen);
  1496.         }    
  1497.         if (write(cacheEntry->dataFD,cacheEntry->rowBuf,
  1498.             cacheEntry->rowLen + 1) < 0)
  1499.         {
  1500.             sprintf(errMsg,WRITE_ERROR);
  1501.             return(-1);
  1502.         }
  1503.     }
  1504.     else
  1505.     {
  1506.         seekPos = rowNum * (cacheEntry->rowLen + 1);
  1507.         buf = ((char *)cacheEntry->dataMap) + seekPos;
  1508.         if (row)
  1509.         {
  1510.             *buf = 1;
  1511.             bcopy(row, buf+1, cacheEntry->rowLen);
  1512.         }
  1513.         else
  1514.         {
  1515.             bcopy(cacheEntry->rowBuf, buf, cacheEntry->rowLen+1);
  1516.         }
  1517.     }
  1518.     return(0);
  1519. }
  1520.  
  1521. #else
  1522.  
  1523. int writeRow(cacheEntry,row,rowNum)
  1524.     cache_t    *cacheEntry;
  1525.     char    *row;
  1526.     u_int    rowNum;
  1527. {
  1528.     int    fd;
  1529.     char    active=1;
  1530.  
  1531.     msqlTrace(TRACE_IN,"writeRow()");
  1532.     if (rowNum == NO_POS)
  1533.     {
  1534.         msqlDebug(MOD_ACCESS,"writeRow() : append to %s\n",
  1535.             (cacheEntry->result)?cacheEntry->resInfo:
  1536.             cacheEntry->table);
  1537.     }
  1538.     else
  1539.     {
  1540.         msqlDebug(MOD_ACCESS,"writeRow() : write at row %u of %s\n",
  1541.             rowNum, (cacheEntry->result)?cacheEntry->resInfo:
  1542.             cacheEntry->table);
  1543.     }
  1544.     *cacheEntry->rowBuf = active;
  1545.     fd = cacheEntry->dataFD;
  1546.     if (rowNum == NO_POS)  /* append */
  1547.     {
  1548.         lseek(fd,(off_t)0, SEEK_END);
  1549.     }
  1550.     else
  1551.     {
  1552.         lseek(fd, (off_t)rowNum * (cacheEntry->rowLen + 1), SEEK_SET);
  1553.     }
  1554.     if (row)
  1555.     {
  1556.         bcopy(row,cacheEntry->rowBuf+1, cacheEntry->rowLen);
  1557.     }
  1558.     if (write(fd,cacheEntry->rowBuf, cacheEntry->rowLen + 1) < 0)
  1559.     {
  1560.         sprintf(errMsg,WRITE_ERROR);
  1561.         msqlTrace(TRACE_OUT,"writeRow()");
  1562.         return(-1);
  1563.     }
  1564.     msqlTrace(TRACE_OUT,"writeRow()");
  1565.     return(0);
  1566. }
  1567.  
  1568. #endif
  1569.  
  1570.  
  1571.  
  1572. #ifdef HAVE_MMAP
  1573.  
  1574. int writeKey(cacheEntry ,key,rowNum)
  1575.     cache_t    *cacheEntry;
  1576.     pkey_t    *key;
  1577.     u_int    rowNum;
  1578. {
  1579.     char    active = 1;
  1580.     REG     off_t    seekPos;
  1581.     char    *buf;
  1582.  
  1583.  
  1584.     setupKey(cacheEntry,key);
  1585.     *cacheEntry->keyBuf = active;
  1586.     if (rowNum == NO_POS)  /* append and flag remap */
  1587.     {
  1588.         cacheEntry->remapKey = 1;
  1589.         lseek(cacheEntry->keyFD,(off_t)0, SEEK_END);
  1590.         if (write(cacheEntry->keyFD,cacheEntry->keyBuf,
  1591.             cacheEntry->keyLen + 1) < 0)
  1592.             return(-1);
  1593.     }
  1594.     else
  1595.     {
  1596.         seekPos = rowNum * (cacheEntry->keyLen + 1);
  1597.         buf = ((char *)cacheEntry->keyMap) + seekPos;
  1598.         (void) bcopy(cacheEntry->keyBuf, buf,cacheEntry->keyLen + 1);
  1599.     }
  1600.     return(0);
  1601. }
  1602. #else
  1603.  
  1604. int writeKey(cacheEntry,key,rowNum)
  1605.     cache_t    *cacheEntry;
  1606.     pkey_t    *key;
  1607.     u_int    rowNum;
  1608. {
  1609.     int    fd;
  1610.     char    active=1;
  1611.  
  1612.     msqlTrace(TRACE_IN,"writeKey()");
  1613.     setupKey(cacheEntry,key);
  1614.     *cacheEntry->keyBuf = active;
  1615.     fd = cacheEntry->keyFD;
  1616.     if (rowNum == NO_POS)  /* append */
  1617.     {
  1618.         lseek(fd,(off_t)0, SEEK_END);
  1619.     }
  1620.     else
  1621.     {
  1622.         lseek(fd, (off_t)rowNum * (cacheEntry->keyLen + 1), SEEK_SET);
  1623.     }
  1624.     if (write(fd,cacheEntry->keyBuf, cacheEntry->keyLen + 1) < 0)
  1625.     {
  1626.         sprintf(errMsg,KEY_WRITE_ERROR);
  1627.         msqlTrace(TRACE_OUT,"writeKey()");
  1628.         return(-1);
  1629.     }
  1630.     msqlTrace(TRACE_OUT,"writeKey()");
  1631.     return(0);
  1632. }
  1633.  
  1634.  
  1635.  
  1636. #endif
  1637.  
  1638.  
  1639. /****************************************************************************
  1640. **     _readRow
  1641. **
  1642. **    Purpose    : Grab a row from a datafile
  1643. **    Args    : datafile FD, length the row, pointer to active flag buf
  1644. **    Returns    : pointer to static row buffer
  1645. **    Notes    : The original version of this routine bcopy()'ed the
  1646. **          row into a space provided by the caller.  Profiling
  1647. **          showed that bcopy() took as much execution time as
  1648. **           read() (although there were 8 reads and 10,000+
  1649. **          bcopy()'s on the sample run).  Returning a pointer and 
  1650. **          then just copying the bits we need for memory allignment is
  1651. **          much faster (ie. 1/7 the amount of time in bcopy for
  1652. **          no loss elsewhere).
  1653. */
  1654.  
  1655. #ifdef HAVE_MMAP
  1656. char *readRow(cacheEntry,active,rowNum)
  1657.     cache_t    *cacheEntry;
  1658.     char    *active;
  1659.     u_int    rowNum;
  1660. {
  1661.     REG     off_t    seekPos;
  1662.     char    *buf;
  1663.  
  1664.  
  1665.     seekPos = rowNum * (cacheEntry->rowLen + 1);
  1666.     if ((seekPos >= cacheEntry->size) || (!cacheEntry->dataMap))
  1667.     {
  1668.         msqlDebug(MOD_ACCESS,"readRow() : %u of %s - No Such Row \n",
  1669.             rowNum, (cacheEntry->result)?cacheEntry->resInfo:
  1670.             cacheEntry->table);
  1671.         *active = 0;
  1672.         return(NULL);
  1673.     }
  1674.     buf = ((char *)cacheEntry->dataMap) + seekPos;
  1675.     *active = *buf;
  1676.     msqlDebug(MOD_ACCESS,"readRow() : %u of %s - %s\n",
  1677.         rowNum, (cacheEntry->result)?cacheEntry->resInfo:
  1678.         cacheEntry->table,(*active)?"Active":"Inactive");
  1679.     return(((char *)buf) + 1);
  1680. }
  1681. #else
  1682.  
  1683. char *readRow(cacheEntry,active,rowNum)
  1684.     cache_t    *cacheEntry;
  1685.         char    *active;
  1686.         u_int     rowNum;
  1687. {
  1688.         int     numBytes,
  1689.         numRows,
  1690.                 maxRead,
  1691.         rowLen,
  1692.         fd;
  1693.         REG     int    offset;
  1694.  
  1695.  
  1696.     msqlTrace(TRACE_IN,"readRow()");
  1697.     rowLen = cacheEntry->rowLen;
  1698.     fd = cacheEntry->dataFD;
  1699.  
  1700.     /*
  1701.     ** A row num of NO_POS forces initialisation
  1702.     */ 
  1703.         if (rowNum == NO_POS)
  1704.         {
  1705.         msqlDebug(MOD_ACCESS,"readRow() : Read buffer initialised\n");
  1706.         cacheEntry->firstRow = cacheEntry->lastRow = -1;
  1707.         *active=0;
  1708.         msqlTrace(TRACE_OUT,"readRow()");
  1709.         return(NULL);
  1710.     }
  1711.  
  1712.     /*
  1713.     ** If the row isn't in the buf, load it
  1714.     */
  1715.     if ((int)rowNum < (int)cacheEntry->firstRow || 
  1716.         (int)rowNum > (int)cacheEntry->lastRow)
  1717.     {
  1718.         /*
  1719.         ** Grab as many rows as we can fit in the buffer.
  1720.         ** If the desired row is one more than the lastRow,
  1721.         ** we can just read as the file pointer will be in
  1722.         ** the right spot
  1723.         */
  1724.                 maxRead = (BUF_SIZE / (rowLen+1)) * (rowLen+1);
  1725.         lseek(fd, (off_t)rowNum * (rowLen+1), SEEK_SET);
  1726.                 numBytes = read(fd,cacheEntry->readBuf,maxRead);
  1727.                 if (numBytes < 1)
  1728.         {
  1729.             cacheEntry->firstRow = cacheEntry->lastRow = -1;
  1730.             *active=0;
  1731.             msqlDebug(MOD_ACCESS,
  1732.                 "readRow() : %u of %s - No Such Row \n",
  1733.                 rowNum,(cacheEntry->result)?cacheEntry->resInfo:
  1734.                 cacheEntry->table);
  1735.             msqlTrace(TRACE_OUT,"readRow()");
  1736.                         return(NULL);
  1737.         }
  1738.                 numRows = numBytes / (rowLen + 1);
  1739.         cacheEntry->firstRow = rowNum;
  1740.         cacheEntry->lastRow = rowNum + numRows - 1;
  1741.         }
  1742.         offset = (rowNum - cacheEntry->firstRow) * (rowLen + 1);
  1743.         *active = *(char *)(cacheEntry->readBuf + offset);
  1744.  
  1745.     msqlDebug(MOD_ACCESS,"readRow() : %u of %s - %s\n",
  1746.         rowNum, (cacheEntry->result)?cacheEntry->resInfo:
  1747.         cacheEntry->table,(*active)?"Active":"Inactive");
  1748.     msqlTrace(TRACE_OUT,"readRow()");
  1749.         return((char *)(cacheEntry->readBuf + offset + 1));
  1750. }
  1751.  
  1752. #endif
  1753.  
  1754.  
  1755.  
  1756.  
  1757. #ifdef HAVE_MMAP
  1758.  
  1759. u_int readKey(cacheEntry,key)
  1760.     cache_t    *cacheEntry;
  1761.     pkey_t    *key;
  1762. {
  1763.     REG     off_t    seekPos;
  1764.     u_int    rowNum,
  1765.         maxRow;
  1766.     char    *buf;
  1767.  
  1768.  
  1769.     setupKey(cacheEntry,key);
  1770.     rowNum = 0;
  1771.     maxRow = cacheEntry->keySize / (cacheEntry->keyLen + 1);
  1772.     while(rowNum < maxRow)
  1773.     {
  1774.         seekPos = rowNum * (cacheEntry->keyLen + 1);
  1775.         if ((seekPos > cacheEntry->keySize) || !cacheEntry->keyMap)
  1776.         {
  1777.             return(NO_POS);
  1778.         }
  1779.         buf = ((char *)cacheEntry->keyMap) + seekPos;
  1780.         if (*buf)
  1781.         {
  1782.             if(bcmp(cacheEntry->keyBuf+1,buf+1,cacheEntry->keyLen)==0)
  1783.             {
  1784.                 return(rowNum);
  1785.             }
  1786.         }
  1787.         rowNum++;
  1788.     }
  1789.     return(NO_POS);
  1790. }
  1791.  
  1792. #else
  1793.  
  1794. u_int readKey(cacheEntry,key)
  1795.     cache_t    *cacheEntry;
  1796.     pkey_t    *key;
  1797. {
  1798.         int     numBytes,
  1799.                 maxRead,
  1800.         fd;
  1801.         REG     int    rowLen,
  1802.             numRows,
  1803.             curRow;
  1804.     char        *cp;
  1805.  
  1806.  
  1807.     msqlTrace(TRACE_IN,"readKey()");
  1808.     setupKey(cacheEntry,key);
  1809.     rowLen = cacheEntry->keyLen;
  1810.     fd = cacheEntry->keyFD;
  1811.     lseek(fd,(off_t)0,SEEK_SET);
  1812.     maxRead = (BUF_SIZE / (rowLen+1)) * (rowLen+1);
  1813.     numBytes = read(fd,readKeyBuf,maxRead);
  1814.     numRows = numBytes / (rowLen + 1);
  1815.     curRow = 0;
  1816.     cp = readKeyBuf;
  1817.     while(numBytes)
  1818.     {
  1819.         if (curRow >= numRows)
  1820.         {
  1821.                     numBytes = read(fd,readKeyBuf,maxRead);
  1822.                     numRows += numBytes / (rowLen + 1);
  1823.             cp = readKeyBuf;
  1824.             continue;
  1825.         }
  1826.         if (*cp)
  1827.         {
  1828.             if(bcmp(cacheEntry->keyBuf + 1, cp+1, rowLen) == 0)
  1829.             {
  1830.                 msqlTrace(TRACE_OUT,"readKey()");
  1831.                 return(curRow);
  1832.             }
  1833.         }
  1834.         curRow++;
  1835.         cp += rowLen + 1;
  1836.         }
  1837.     msqlTrace(TRACE_OUT,"readKey()");
  1838.     return(NO_POS);
  1839. }
  1840.  
  1841. #endif
  1842.  
  1843.  
  1844.  
  1845. /****************************************************************************
  1846. **     _deleteRow
  1847. **
  1848. **    Purpose    : Invalidate a row in the table
  1849. **    Args    : datafile FD, rowlength, desired row location
  1850. **    Returns    : -1 on error
  1851. **    Notes    : This only sets the row header byte to 0 indicating
  1852. **          that it's no longer in use
  1853. */
  1854.  
  1855. int deleteRow(cacheEntry,rowNum)
  1856.     cache_t    *cacheEntry;
  1857.     u_int    rowNum;
  1858. {
  1859.     char    *activePtr;
  1860.     int    rowLen;
  1861.  
  1862. #ifndef HAVE_MMAP
  1863.     int    fd;
  1864.     char    activeBuf;
  1865. #endif
  1866.  
  1867.     msqlTrace(TRACE_IN,"deleteRow()");
  1868.     msqlDebug(MOD_ACCESS,"deleteRow() : row %u of %s\n",
  1869.         rowNum, (cacheEntry->result)?cacheEntry->resInfo:
  1870.         cacheEntry->table);
  1871.     rowLen = cacheEntry->rowLen;
  1872.  
  1873. #ifdef HAVE_MMAP
  1874.     activePtr = ((char *)cacheEntry->dataMap) + (rowNum * (rowLen + 1));
  1875.     *activePtr = 0;
  1876. #else
  1877.     fd = cacheEntry->dataFD;
  1878.     if (lseek(fd,(off_t)rowNum * (rowLen+1), SEEK_SET) < 0)
  1879.     {
  1880.         sprintf(errMsg,SEEK_ERROR);
  1881.         msqlTrace(TRACE_OUT,"deleteRow()");
  1882.         return(-1);
  1883.     }
  1884.     activeBuf = 0;
  1885.     if (write(fd,&activeBuf,1) < 0)
  1886.     {
  1887.         sprintf(errMsg,WRITE_ERROR);
  1888.         msqlTrace(TRACE_OUT,"deleteRow()");
  1889.         return(-1);
  1890.     }
  1891.     /*
  1892.     ** Force a reload of the data buffer else we won't see the new
  1893.     ** active value.
  1894.     */
  1895.     (void) readRow(cacheEntry,&activeBuf, NO_POS);
  1896. #endif
  1897.     msqlTrace(TRACE_OUT,"deleteRow()");
  1898.     return(0);
  1899. }
  1900.  
  1901.  
  1902. int deleteKey(cacheEntry,rowNum)
  1903.     cache_t    *cacheEntry;
  1904.     u_int    rowNum;
  1905. {
  1906.     char    *activePtr;
  1907.     int    rowLen;
  1908.  
  1909. #ifndef HAVE_MMAP
  1910.     char    activeBuf = 0;
  1911.     int    fd;
  1912. #endif
  1913.  
  1914.     msqlTrace(TRACE_IN,"deleteKey()");
  1915.     rowLen = cacheEntry->keyLen;
  1916.  
  1917. #ifdef HAVE_MMAP
  1918.     if (cacheEntry->keyMap)
  1919.     {
  1920.         activePtr = ((char *)cacheEntry->keyMap) + 
  1921.             (rowNum * (rowLen + 1));
  1922.         *activePtr = 0;
  1923.     }
  1924. #else
  1925.  
  1926.     fd = cacheEntry->keyFD;
  1927.     if (fd >= 0)
  1928.     {
  1929.         if (lseek(fd,(off_t)rowNum * (rowLen+1), SEEK_SET) < 0)
  1930.         {
  1931.             sprintf(errMsg,KEY_SEEK_ERROR);
  1932.             msqlTrace(TRACE_OUT,"deleteKey()");
  1933.             return(-1);
  1934.         }
  1935.         activeBuf = 0;
  1936.         if (write(fd,&activeBuf,1) < 0)
  1937.         {
  1938.             sprintf(errMsg,KEY_WRITE_ERROR);
  1939.             msqlTrace(TRACE_OUT,"deleteKey()");
  1940.             return(-1);
  1941.         }
  1942.     }
  1943. #endif
  1944.     msqlTrace(TRACE_OUT,"deleteKey()");
  1945.     return(0);
  1946. }
  1947.  
  1948.  
  1949.  
  1950.  
  1951.  
  1952.  
  1953. /****************************************************************************
  1954. **     _checkNullFields
  1955. **
  1956. **    Purpose    : Ensure that fields flagged "not null" have a value
  1957. **    Args    : table row
  1958. **    Returns    : -1 on error
  1959. **    Notes    :
  1960. */
  1961.  
  1962. static int checkNullFields(cacheEntry,row)
  1963.     cache_t    *cacheEntry;
  1964.     char    *row;
  1965. {
  1966.     REG     field_t    *curField;
  1967.     REG     int    offset;
  1968.  
  1969.     msqlTrace(TRACE_IN,"checkNullFields()");
  1970.     offset = 0;
  1971.     curField = cacheEntry->def;
  1972.     while(curField)
  1973.     {
  1974.         if (!*(row + offset) && (curField->flags & NOT_NULL_FLAG))
  1975.         {
  1976.             sprintf(errMsg,BAD_NULL_ERROR, curField->name);
  1977.             msqlDebug(MOD_ERR,"Field \"%s\" cannot be null\n",
  1978.                 curField->name);
  1979.             msqlTrace(TRACE_OUT,"checkNullFields()");
  1980.             return(-1);
  1981.         }
  1982.         offset += curField->length + 1;
  1983.         curField = curField->next;
  1984.     }
  1985.     msqlTrace(TRACE_OUT,"checkNullFields()");
  1986.     return(0);
  1987. }
  1988.  
  1989.  
  1990.  
  1991. static void qualifyFields(table,fields)
  1992.     char    *table;
  1993.     field_t    *fields;
  1994. {
  1995.     field_t    *curField;
  1996.  
  1997.     msqlTrace(TRACE_IN,"qualifyField()");
  1998.     curField = fields;
  1999.     while(curField)
  2000.     {
  2001.         if(*(curField->table) == 0)
  2002.         {
  2003.             (void)strcpy(curField->table,table);
  2004.         }
  2005.         curField=curField->next;
  2006.     }
  2007.     msqlTrace(TRACE_OUT,"qualifyField()");
  2008. }
  2009.  
  2010.  
  2011. static void qualifyConds(table,conds)
  2012.     char    *table;
  2013.     cond_t    *conds;
  2014. {
  2015.     cond_t    *curCond;
  2016.  
  2017.     msqlTrace(TRACE_IN,"qualifyConds()");
  2018.     curCond = conds;
  2019.     while(curCond)
  2020.     {
  2021.         if(*(curCond->table) == 0)
  2022.         {
  2023.             (void)strcpy(curCond->table,table);
  2024.         }
  2025.         curCond=curCond->next;
  2026.     }
  2027.     msqlTrace(TRACE_OUT,"qualifyConds()");
  2028. }
  2029.  
  2030.  
  2031.  
  2032. static void qualifyOrder(table,order)
  2033.     char    *table;
  2034.     order_t    *order;
  2035. {
  2036.     order_t    *curOrder;
  2037.  
  2038.     msqlTrace(TRACE_IN,"qualifyOrder()");
  2039.     curOrder = order;
  2040.     while(curOrder)
  2041.     {
  2042.         if(*(curOrder->table) == 0)
  2043.         {
  2044.             (void)strcpy(curOrder->table,table);
  2045.         }
  2046.         curOrder=curOrder->next;
  2047.     }
  2048.     msqlTrace(TRACE_OUT,"qualifyOrder()");
  2049. }
  2050.  
  2051.  
  2052.  
  2053. /****************************************************************************
  2054. **     _setupFields
  2055. **
  2056. **    Purpose    : Determine the byte offset into a row of the desired fields
  2057. **    Args    : Empty field list (field location) array,
  2058. **          List of desired fields
  2059. **    Returns    : -1 on error
  2060. **    Notes    : The field list array holds the byte offsets for the
  2061. **          fields.  ie. array element 0 will hold the byte offset
  2062. **          of the first desired field etc.
  2063. */
  2064.  
  2065. static int setupFields(cacheEntry,flist, fields, keyPtr)
  2066.     cache_t    *cacheEntry;
  2067.     int    *flist;
  2068.     field_t    *fields;
  2069.     pkey_t    **keyPtr;
  2070. {
  2071.     REG     field_t    *curField,
  2072.             *fieldDef;
  2073.     int    numFields,
  2074.         *curFL,
  2075.         curOffset;
  2076.     static    pkey_t    key;
  2077.  
  2078.  
  2079.  
  2080.     msqlTrace(TRACE_IN,"setupFields()");
  2081.     numFields = 0;
  2082.     curField = fields;
  2083.     curFL = flist;
  2084.     if (keyPtr)
  2085.     {
  2086.         *keyPtr = NULL;
  2087.     }
  2088.     while(curField)
  2089.     {
  2090.         numFields++;
  2091.         if (numFields < MAX_FIELDS)
  2092.             *curFL++ = -1;
  2093.         curField=curField->next;
  2094.     }
  2095.     if (numFields > MAX_FIELDS)
  2096.     {
  2097.         sprintf(errMsg,FIELD_COUNT_ERROR);
  2098.         msqlDebug(MOD_ERR,"Too many fileds in query\n");
  2099.         msqlTrace(TRACE_OUT,"setupFields()");
  2100.         return(-1);
  2101.     }
  2102.     *curFL = -1;
  2103.     
  2104.     curField = fields;
  2105.     curFL = flist;
  2106.     while(curField)
  2107.     {
  2108.         fieldDef = cacheEntry->def;
  2109.         curOffset = 0;
  2110.         while(fieldDef)
  2111.         {
  2112.         if(strcmp(curField->name,fieldDef->name) == 0 &&
  2113.            strcmp(curField->table,fieldDef->table) == 0)
  2114.         {
  2115.             curField->type = fieldDef->type;
  2116.             curField->length = fieldDef->length;
  2117.             curField->flags = fieldDef->flags;
  2118.             if (curField->flags & PRI_KEY_FLAG)
  2119.             {
  2120.                 if (keyPtr)
  2121.                 {
  2122.                     key.table = curField->table;
  2123.                     key.name = curField->name;
  2124.                     key.type = curField->type;
  2125.                     key.length = curField->length;
  2126.                     key.value = curField->value;
  2127.                     key.op = 0;
  2128.                     *keyPtr = &key;
  2129.                 }
  2130.             }
  2131.             *curFL = curOffset;
  2132.             if (!curField->value)
  2133.                 break;
  2134.             if (!curField->value->nullVal)
  2135.             {
  2136.                 switch(curField->type)
  2137.                 {
  2138.                     case INT_TYPE:
  2139.                         if(curField->value->type
  2140.                             != INT_TYPE)
  2141.                         {
  2142.                             sprintf(errMsg,
  2143.                                 TYPE_ERROR,
  2144.                                 curField->name);
  2145.                             msqlDebug(MOD_ERR,TYPE_ERROR,
  2146.                                 curField->name);
  2147.                             return(-1);
  2148.                         }
  2149.                         break;
  2150.         
  2151.                     case CHAR_TYPE:
  2152.                         if(curField->value->type
  2153.                             != CHAR_TYPE)
  2154.                         {
  2155.                             sprintf(errMsg,
  2156.                                 TYPE_ERROR,
  2157.                                 curField->name);
  2158.                             msqlDebug(MOD_ERR,TYPE_ERROR,
  2159.                                 curField->name);
  2160.                             return(-1);
  2161.                         }
  2162.                         break;
  2163.  
  2164.                     case REAL_TYPE:
  2165.                         if(curField->value->type
  2166.                             == INT_TYPE)
  2167.                         {
  2168.                           curField->value->val.realVal
  2169.                           = curField->value->val.intVal;
  2170.                                       curField->value->type = 
  2171.                             REAL_TYPE;
  2172.                         }
  2173.                         if(curField->value->type
  2174.                             != REAL_TYPE)
  2175.                         {
  2176.                             sprintf(errMsg,
  2177.                                 TYPE_ERROR,
  2178.                                 curField->name);
  2179.                             msqlDebug(MOD_ERR,TYPE_ERROR,
  2180.                                 curField->name);
  2181.                             return(-1);
  2182.                         }
  2183.                         break;
  2184.                 }
  2185.             }
  2186.             break;
  2187.         }
  2188.         curOffset += fieldDef->length+1; /* +1 for null indicator */
  2189.         fieldDef = fieldDef->next;
  2190.         }
  2191.         if(!fieldDef)  /* Bad entry */
  2192.         {
  2193.         if (curField->table)
  2194.         {
  2195.             sprintf(errMsg,BAD_FIELD_ERROR,
  2196.                 curField->table,curField->name);
  2197.             msqlDebug(MOD_ERR,"Unknown field \"%s.%s\"\n",
  2198.                 curField->table,curField->name);
  2199.             msqlTrace(TRACE_OUT,"setupFields()");
  2200.             return(-1);
  2201.         }
  2202.         else
  2203.         {
  2204.             sprintf(errMsg,BAD_FIELD_2_ERROR,curField->name);
  2205.             msqlDebug(MOD_ERR,"Unknown field \"%s\"\n",curField->name);
  2206.             msqlTrace(TRACE_OUT,"setupFields()");
  2207.             return(-1);
  2208.         }
  2209.         }
  2210.         curFL++;
  2211.         curField = curField->next;
  2212.     }
  2213.     msqlTrace(TRACE_OUT,"setupFields()");
  2214.     return(0);
  2215. }
  2216.  
  2217.  
  2218.  
  2219.  
  2220.  
  2221. /****************************************************************************
  2222. **     _setupConds
  2223. **
  2224. **    Purpose    : Determine the byte offset into a row for conditional
  2225. **          data.
  2226. **    Args    : Condition list (field location) array,
  2227. **          List of fileds used in conditionals
  2228. **    Returns    : -1 on error
  2229. **    Notes    : As per setupFields.
  2230. */
  2231.  
  2232. static int setupConds(cacheEntry,clist, conds, keyPtr)
  2233.     cache_t    *cacheEntry;
  2234.     int    *clist;
  2235.     cond_t    *conds;
  2236.     pkey_t    **keyPtr;
  2237. {
  2238.     REG     cond_t    *curCond;
  2239.     REG     field_t    *fieldDef;
  2240.     int    numConds,
  2241.         *curFL,
  2242.         curOffset;
  2243.     char    *name,
  2244.         *length,
  2245.         *type;
  2246.     static    pkey_t    key;
  2247.  
  2248.  
  2249.     msqlTrace(TRACE_IN,"setupConds()");
  2250.     numConds = 0;
  2251.     curCond = conds;
  2252.     curFL = clist;
  2253.     *keyPtr = NULL;
  2254.     while(curCond)
  2255.     {
  2256.         numConds++;
  2257.         if (numConds < MAX_FIELDS)
  2258.             *curFL++ = -1;
  2259.         curCond=curCond->next;
  2260.     }
  2261.     if (numConds > MAX_FIELDS)
  2262.     {
  2263.         sprintf(errMsg,COND_COUNT_ERROR);
  2264.         msqlDebug(MOD_ERR,"Too many fields in condition\n");
  2265.         msqlTrace(TRACE_OUT,"setupConds()");
  2266.         return(-1);
  2267.     }
  2268.     *curFL = -1;
  2269.     
  2270.     curCond = conds;
  2271.     curFL = clist;
  2272.     while(curCond)
  2273.     {
  2274.         fieldDef = cacheEntry->def;
  2275.         curOffset = 0;
  2276.         while(fieldDef)
  2277.         {
  2278.             if(strcmp(curCond->name,fieldDef->name) == 0 &&
  2279.                strcmp(curCond->table,fieldDef->table) == 0)
  2280.             {
  2281.                 curCond->type = fieldDef->type;
  2282.                 curCond->length = fieldDef->length;
  2283.                 *curFL = curOffset;
  2284.                 if (fieldDef->flags & PRI_KEY_FLAG)
  2285.                 {
  2286.                     key.name = fieldDef->name;
  2287.                     key.type = fieldDef->type;
  2288.                     key.length = fieldDef->length;
  2289.                     key.value = curCond->value;
  2290.                     key.op = curCond->op;
  2291.                     *keyPtr = &key;
  2292.                 }
  2293.                 break;
  2294.             }
  2295.             curOffset += fieldDef->length+1; /* +1 for null ind */
  2296.             fieldDef = fieldDef->next;
  2297.         }
  2298.         if (!fieldDef)
  2299.         {
  2300.             sprintf(errMsg,BAD_FIELD_2_ERROR, curCond->name);
  2301.             msqlDebug(MOD_ERR,"Unknown field in where clause \"%s\"\n",
  2302.                 curCond->name);
  2303.             msqlTrace(TRACE_OUT,"setupConds()");
  2304.             return(-1);
  2305.         }
  2306.         curFL++;
  2307.         curCond = curCond->next;
  2308.     }
  2309.     msqlTrace(TRACE_OUT,"setupConds()");
  2310.     return(0);
  2311. }
  2312.  
  2313.  
  2314.  
  2315. /****************************************************************************
  2316. **     _setupOrder
  2317. **
  2318. **    Purpose    : Determine the byte offset into a row for order
  2319. **          data.
  2320. **    Args    : Order list (field location) array,
  2321. **          List of fileds used in order
  2322. **    Returns    : -1 on error
  2323. **    Notes    : As per setupFields.
  2324. */
  2325.  
  2326. static int setupOrder(cacheEntry,olist, order)
  2327.     cache_t    *cacheEntry;
  2328.     int    *olist;
  2329.     order_t    *order;
  2330. {
  2331.     REG     order_t    *curOrder;
  2332.     REG     field_t    *fieldDef;
  2333.     int    numOrder,
  2334.         *curFL,
  2335.         curOffset;
  2336.     char    *name,
  2337.         *length,
  2338.         *type;
  2339.  
  2340.     msqlTrace(TRACE_IN,"setupOrder()");
  2341.     numOrder = 0;
  2342.     curOrder = order;
  2343.     curFL = olist;
  2344.     while(curOrder)
  2345.     {
  2346.         numOrder++;
  2347.         if (numOrder < MAX_FIELDS)
  2348.             *curFL++ = -1;
  2349.         curOrder=curOrder->next;
  2350.     }
  2351.     if (numOrder > MAX_FIELDS)
  2352.     {
  2353.         sprintf(errMsg,ORDER_COUNT_ERROR);
  2354.         msqlDebug(MOD_ERR,"Too many fields in order specification\n");
  2355.         msqlTrace(TRACE_OUT,"setupOrder()");
  2356.         return(-1);
  2357.     }
  2358.     *curFL = -1;
  2359.     
  2360.     curOrder = order;
  2361.     curFL = olist;
  2362.     while(curOrder)
  2363.     {
  2364.         fieldDef = cacheEntry->def;
  2365.         curOffset = 0;
  2366.         while(fieldDef)
  2367.         {
  2368.             if(strcmp(curOrder->name,fieldDef->name) == 0 &&
  2369.                strcmp(curOrder->table,fieldDef->table) == 0)
  2370.             {
  2371.                 curOrder->type = fieldDef->type;
  2372.                 curOrder->length = fieldDef->length;
  2373.                 *curFL = curOffset;
  2374.                 break;
  2375.             }
  2376.             curOffset += fieldDef->length+1; /* +1 for null ind */
  2377.             fieldDef = fieldDef->next;
  2378.         }
  2379.         if (!fieldDef)
  2380.         {
  2381.             sprintf(errMsg,BAD_FIELD_2_ERROR, curOrder->name);
  2382.             msqlDebug(MOD_ERR,"Unknown field in order clause \"%s\"\n",
  2383.                 curOrder->name);
  2384.             msqlTrace(TRACE_OUT,"setupOrder()");
  2385.             return(-1);
  2386.         }
  2387.         curFL++;
  2388.         curOrder = curOrder->next;
  2389.     }
  2390.     msqlTrace(TRACE_OUT,"setupOrder()");
  2391.     return(0);
  2392. }
  2393.  
  2394.  
  2395.  
  2396.  
  2397.  
  2398.  
  2399.  
  2400. /****************************************************************************
  2401. **     _expandWildCards
  2402. **
  2403. **    Purpose    : Handle "*" in a select clause
  2404. **    Args    : 
  2405. **    Returns    : 
  2406. **    Notes    : This just drops the entire table into the field list
  2407. **          when it finds a "*"
  2408. */
  2409.  
  2410. field_t *expandFieldWildCards(cacheEntry,fields)
  2411.     cache_t    *cacheEntry;
  2412.     field_t    *fields;
  2413. {
  2414.     char    path[255],
  2415.         line[100],
  2416.         *name;
  2417.     REG     field_t    *curField,
  2418.             *fieldDef;
  2419.     field_t    *prevField,
  2420.         *newField,
  2421.         *tmpField,
  2422.         *head;
  2423.  
  2424.  
  2425.     /*
  2426.     ** Scan the field list
  2427.     */
  2428.  
  2429.     msqlTrace(TRACE_IN,"expandWildcard()");
  2430.     head = curField = fields;
  2431.     prevField = NULL;
  2432.     while(curField)
  2433.     {
  2434.         if (strcmp(curField->name,"*") == 0)
  2435.         {
  2436.             /*
  2437.             ** Setup a new entry for each field
  2438.             */
  2439.             fieldDef = cacheEntry->def;
  2440.             while(fieldDef)
  2441.             {
  2442.                 newField = (field_t *)malloc(sizeof(field_t));
  2443.                 strcpy(newField->name,fieldDef->name);
  2444.                 strcpy(newField->table,fieldDef->table);
  2445.                 if (!prevField)
  2446.                 {
  2447.                     head = newField;
  2448.                 }
  2449.                 else
  2450.                     prevField->next = newField;
  2451.                 newField->next = curField->next;
  2452.                 prevField = newField;
  2453.                 fieldDef = fieldDef->next;
  2454.             }
  2455.  
  2456.             /*
  2457.             ** Blow away the wildcard entry
  2458.             */
  2459.             if (curField->type == CHAR_TYPE)
  2460.                 safeFree(curField->value->val.charVal);
  2461.             tmpField = curField;
  2462.             curField = curField->next;
  2463.             safeFree(tmpField);
  2464.         }
  2465.         else
  2466.         {
  2467.             prevField = curField;
  2468.             curField = curField->next;
  2469.         }
  2470.     }
  2471.     msqlTrace(TRACE_OUT,"expandWildcard()");
  2472.     return(head);
  2473. }
  2474.  
  2475.  
  2476.  
  2477. expandTableFields(table)
  2478.     char    *table;
  2479. {
  2480.     cache_t *cacheEntry;
  2481.     extern char *curDB;
  2482.     char    tableName[NAME_LEN];
  2483.  
  2484.     msqlTrace(TRACE_IN,"expandTableFields()");
  2485.     strcpy(tableName,table);
  2486.     if((cacheEntry = loadTableDef(tableName,NULL,curDB)))
  2487.     {
  2488.         fieldHead = expandFieldWildCards(cacheEntry,fieldHead);
  2489.     }
  2490.     msqlTrace(TRACE_OUT,"expandTableFields()");
  2491. }
  2492.  
  2493.  
  2494.  
  2495.  
  2496.  
  2497. /****************************************************************************
  2498. **     _fillRow
  2499. **
  2500. **    Purpose    : Create a new row-buf using the info given
  2501. **    Args    : 
  2502. **    Returns    : 
  2503. **    Notes    : 
  2504. */
  2505.  
  2506.  
  2507. static void fillRow(row,fields,flist)
  2508.     char    *row;
  2509.     field_t    *fields;
  2510.     int    flist[];
  2511. {
  2512.     int    *offset,
  2513.         length;
  2514.     field_t    *curField;
  2515.     char    *cp;
  2516.     int    *ip;
  2517.     double    *fp;
  2518.  
  2519.     msqlTrace(TRACE_IN,"fillRow()");
  2520.     curField = fields;
  2521.     offset = flist;
  2522.     while(curField)
  2523.     {
  2524.         if (!curField->value->nullVal)
  2525.         {
  2526.             cp = row + *offset;
  2527.             *cp = '\001';
  2528.             cp++;
  2529.             switch(curField->type)
  2530.             {
  2531.                 case INT_TYPE:
  2532. #ifndef _CRAY
  2533.                     bcopy(&(curField->value->val.intVal),cp,
  2534.                         sizeof(int));
  2535. #else
  2536.                     packInt32(curField->value->val.intVal,
  2537.                         cp);
  2538. #endif
  2539.                     break;
  2540.         
  2541.                 case CHAR_TYPE:
  2542.                     length=strlen(curField->value->val.charVal);
  2543.                     if (length > curField->length)
  2544.                         length = curField->length;
  2545.                     bcopy(curField->value->val.charVal,cp,
  2546.                         length);
  2547.                     break;
  2548.  
  2549.                 case REAL_TYPE:
  2550.                     bcopy(&(curField->value->val.realVal),cp,
  2551.                         sizeof(double));
  2552.                     break;
  2553.             }
  2554.         }
  2555.         offset++;
  2556.         curField = curField->next;
  2557.     }
  2558.     msqlTrace(TRACE_OUT,"fillRow()");
  2559. }
  2560.  
  2561.  
  2562.  
  2563.  
  2564.  
  2565.  
  2566. /****************************************************************************
  2567. **     _updateValues
  2568. **
  2569. **    Purpose    : Modify a row-buf to reflect the contents of the field list
  2570. **    Args    : 
  2571. **    Returns    : 
  2572. **    Notes    : 
  2573. */
  2574.  
  2575. static void updateValues(row,fields,flist)
  2576.     char    *row;
  2577.     field_t    *fields;
  2578.     int    flist[];
  2579. {
  2580.     int    *offset;
  2581.     field_t    *curField;
  2582.     char    *cp;
  2583.  
  2584.     msqlTrace(TRACE_IN,"updateValues()");
  2585.     curField = fields;
  2586.     offset = flist;
  2587.     while(curField)
  2588.     {
  2589.         cp = row + *offset;
  2590.         if (!curField->value->nullVal)
  2591.                 {
  2592.                         *cp = '\001';
  2593.                         cp++;
  2594.             switch(curField->type)
  2595.             {
  2596.                 case INT_TYPE:
  2597. #ifndef _CRAY
  2598.                     bcopy(&(curField->value->val.intVal),cp,
  2599.                         sizeof(int));
  2600. #else
  2601.                      packInt32(curField->value->val.intVal, 
  2602.                         cp);
  2603. #endif
  2604.                     break;
  2605.         
  2606.                 case CHAR_TYPE:
  2607.                     (void)bzero(cp, curField->length);
  2608.                     strncpy(cp, curField->value->val.charVal,
  2609.                         curField->length);
  2610.                     break;
  2611.  
  2612.                 case REAL_TYPE:
  2613.                     bcopy(&(curField->value->val.realVal),cp,
  2614.                         sizeof(double));
  2615.                     break;
  2616.             }
  2617.         }
  2618.         else
  2619.         {
  2620.             *cp = '\000';
  2621.         }
  2622.         offset++;
  2623.         curField = curField->next;
  2624.     }
  2625.     msqlTrace(TRACE_OUT,"updateValues()");
  2626. }
  2627.  
  2628.  
  2629.  
  2630.  
  2631.  
  2632.  
  2633. /****************************************************************************
  2634. **     _translateValues
  2635. **
  2636. **    Purpose    : Create real field values from the query text
  2637. **    Args    : 
  2638. **    Returns    : 
  2639. **    Notes    : All field values are passed as text in the query
  2640. **          string.  This just converts them to their native format
  2641. */
  2642.  
  2643. #ifdef NOT_DEF
  2644.  
  2645. static void translateValues(fields)
  2646.     field_t    *fields;
  2647. {
  2648.     field_t    *curField;
  2649.  
  2650.     msqlTrace(TRACE_IN,"translateValues()");
  2651.     curField = fields;
  2652.     while(curField)
  2653.     {
  2654.         if (curField->length)
  2655.                 {
  2656.             curField->value->nullVal = 0;
  2657.             switch(curField->type)
  2658.             {
  2659.                 case INT_TYPE:
  2660. #ifndef _CRAY
  2661.                     curField->value->val.intVal =
  2662.                         atoi(curField->textRep);
  2663. #else
  2664.                     packInt32(curField->value->val.intVal,
  2665.                         cp);
  2666. #endif
  2667.                     safeFree(curField->textRep);
  2668.                     break;
  2669.  
  2670.                  case CHAR_TYPE:
  2671.                     curField->value->val.charVal = 
  2672.                         curField->textRep;
  2673.                     break;
  2674.  
  2675.                 case REAL_TYPE:
  2676.                     sscanf(curField->textRep,"%lf",
  2677.                          &(curField->value->val.realVal));
  2678.                     safeFree(curField->textRep);
  2679.                     break;
  2680.             }
  2681.         }
  2682.         else 
  2683.         {
  2684.             curField->value->nullVal = 0;
  2685.         }
  2686.         curField = curField->next;
  2687.     }
  2688.     msqlTrace(TRACE_OUT,"translateValues()");
  2689. }
  2690.  
  2691. #endif
  2692.  
  2693.  
  2694.  
  2695.  
  2696.  
  2697.  
  2698. /****************************************************************************
  2699. **     _extractValues
  2700. **
  2701. **    Purpose    : Rip the required data from a row-buf
  2702. **    Args    : 
  2703. **    Returns    : 
  2704. **    Notes    : 
  2705. */
  2706.  
  2707. static void extractValues(row,fields,flist)
  2708.     u_char    *row;
  2709.     field_t    *fields;
  2710.     int    flist[];
  2711. {
  2712.     field_t    *curField;
  2713.     u_char    *cp;
  2714.     int    ip,
  2715.         *offset;
  2716.     double    *fp;
  2717.     char    buf[8];
  2718.  
  2719.     msqlTrace(TRACE_IN,"extractValues()");
  2720.     curField = fields;
  2721.     offset = flist;
  2722.     while(curField)
  2723.     {
  2724.         if (curField->value)
  2725.         {
  2726.             freeValue(curField->value);
  2727.             curField->value = NULL;
  2728.         }
  2729.         if ( * (row + *offset)) 
  2730.         {
  2731.             curField->value=NULL;
  2732.             switch(curField->type)
  2733.             {
  2734.                 case INT_TYPE:
  2735. #ifndef _CRAY
  2736.                     bcopy(row + *offset + 1,&ip,4);
  2737.                     curField->value =(val_t *)
  2738.                         fillValue(&ip,INT_TYPE);
  2739. #else
  2740.                     curField->value = (val_t*)fillValue(
  2741.                         row + *offset + 1, INT_TYPE);
  2742. #endif
  2743.                     break;
  2744.  
  2745.                 case CHAR_TYPE:
  2746.                     cp = (u_char *)row + *offset + 1;
  2747.                     curField->value = (val_t *)
  2748.                         fillValue(cp, CHAR_TYPE,
  2749.                         curField->length);
  2750.                     break;
  2751.  
  2752.                 case REAL_TYPE:
  2753.                     bcopy(row + *offset + 1,buf,8);
  2754.                     fp = (double *)buf;
  2755.                     curField->value =(val_t *)
  2756.                         fillValue(fp,REAL_TYPE);
  2757.                     break;
  2758.             }
  2759.         } 
  2760.         else 
  2761.         {
  2762.             curField->value = (val_t *)nullValue();
  2763.         }
  2764.         curField = curField->next;
  2765.         offset++;
  2766.     }
  2767.     msqlTrace(TRACE_OUT,"extractValues()");
  2768. }
  2769.  
  2770.  
  2771.  
  2772. static char    regErrFlag;
  2773.  
  2774. void regerror()
  2775. {
  2776.     regErrFlag++;
  2777. }
  2778.  
  2779.  
  2780.  
  2781.  
  2782. static int regexpTest(str,re,maxLen)
  2783.     char    *str,
  2784.         *re;
  2785.     int    maxLen;
  2786. {
  2787.     char    regbuf[1024],
  2788.         hold;
  2789.     REG     char *cp1, *cp2;
  2790.     regexp    *reg;
  2791.     int    res;
  2792.  
  2793.     /*
  2794.     ** Map an SQL regexp into a UNIX regexp
  2795.     */
  2796.     cp1 = re;
  2797.     cp2 = regbuf;
  2798.     (void)bzero(regbuf,sizeof(regbuf));
  2799.     *cp2++ = '^';
  2800.     while(*cp1 && maxLen)
  2801.     {
  2802.         switch(*cp1)
  2803.         {
  2804.             case '\\':
  2805.                 if (*(cp1+1))
  2806.                 {
  2807.                     cp1++;
  2808.                     *cp2 = *cp1;
  2809.                 }
  2810.                 cp1++;
  2811.                 cp2++;
  2812.                 break;
  2813.  
  2814.             case '_':
  2815.                 *cp2++ = '.';
  2816.                 cp1++;
  2817.                 break;
  2818.  
  2819.             case '%':
  2820.                 *cp2++ = '.';
  2821.                 *cp2++ = '*';
  2822.                 cp1++;
  2823.                 break;
  2824.  
  2825.             case '.':
  2826.             case '*':
  2827.             case '+':
  2828.                 *cp2++ = '\\';
  2829.                 *cp2++ = *cp1++;
  2830.                 break;
  2831.  
  2832.             default:
  2833.                 *cp2++ = *cp1++;
  2834.                 break;
  2835.         }
  2836.     }
  2837.     *cp2 = '$';
  2838.  
  2839.     /*
  2840.     ** Do the regexp thang.  We do an ugly hack here : The data of
  2841.     ** a field may be exactly the same length as the field itself.
  2842.     ** Seeing as the regexp routines work on null rerminated strings
  2843.     ** if the field is totally full we get field over-run.  So,
  2844.     ** store the value of the last byte, null it out, run the regexp
  2845.     ** and then reset it (hey, I said it was ugly).
  2846.     */
  2847.     regErrFlag = 0;
  2848.     hold = *(str + maxLen);
  2849.     *(str + maxLen) = 0;
  2850.     reg = regcomp(regbuf);
  2851.     res = regexec(reg,str);
  2852.     *(str + maxLen) = hold;
  2853.     safeFree(reg);
  2854.     if (regErrFlag)
  2855.     {
  2856.         strcpy(errMsg, BAD_LIKE_ERROR);
  2857.         msqlDebug(MOD_ERR, "Evaluation of LIKE clause failed\n");
  2858.         return(-1);
  2859.     }
  2860.     return(res);
  2861. }
  2862.  
  2863.  
  2864.  
  2865. /****************************************************************************
  2866. **     _intMatch
  2867. **
  2868. **    Purpose    : comparison suite for integer fields.
  2869. **    Args    : 
  2870. **    Returns    : 
  2871. **    Notes    : 
  2872. */
  2873.  
  2874. static int intMatch(v1,v2,op)
  2875.     int    v1, v2, op;
  2876. {
  2877.     int    result;
  2878.  
  2879.     switch(op)
  2880.     {
  2881.         case EQ_OP:
  2882.             result = (v1 == v2);
  2883.             break;
  2884.             
  2885.         case NE_OP:
  2886.             result = (v1 != v2);
  2887.             break;
  2888.             
  2889.         case LT_OP:
  2890.             result = (v1 < v2);
  2891.             break;
  2892.             
  2893.         case LE_OP:
  2894.             result = (v1 <= v2);
  2895.             break;
  2896.             
  2897.         case GT_OP:
  2898.             result = (v1 > v2);
  2899.             break;
  2900.             
  2901.         case GE_OP:
  2902.             result = (v1 >= v2);
  2903.             break;
  2904.     }
  2905.     return(result);
  2906. }
  2907.  
  2908.  
  2909.  
  2910.  
  2911.  
  2912.  
  2913. /****************************************************************************
  2914. **     _charMatch
  2915. **
  2916. **    Purpose    : Comparison suite for text fields
  2917. **    Args    : 
  2918. **    Returns    : 
  2919. **    Notes    : 
  2920. */
  2921.  
  2922. static int charMatch(v1,v2,op,maxLen)
  2923.     char    *v1,
  2924.         *v2;
  2925.     int    op,
  2926.         maxLen;
  2927. {
  2928.     int    result,
  2929.         cmp;
  2930.     REG    char    *c1,*c2;
  2931.     REG    int    offset;
  2932.  
  2933.     if (op != LIKE_OP)
  2934.     {
  2935.         c1 = v1;
  2936.         c2 = v2;
  2937.         offset=0;
  2938.         cmp = 0;
  2939.         while(offset < maxLen)
  2940.         {
  2941.             if ((cmp = *c1 - *c2) != 0)
  2942.                 break;
  2943.             if ( *c1==0 || *c2==0)
  2944.                 break;
  2945.             c1++;
  2946.             c2++;
  2947.             offset++;
  2948.         }
  2949.     }
  2950.     switch(op)
  2951.     {
  2952.         case EQ_OP:
  2953.             result = (cmp == 0);
  2954.             break;
  2955.             
  2956.         case NE_OP:
  2957.             result = (cmp != 0);
  2958.             break;
  2959.             
  2960.         case LT_OP:
  2961.             result = (cmp < 0);
  2962.             break;
  2963.             
  2964.         case LE_OP:
  2965.             result = (cmp <= 0);
  2966.             break;
  2967.             
  2968.         case GT_OP:
  2969.             result = (cmp > 0);
  2970.             break;
  2971.             
  2972.         case GE_OP:
  2973.             result = (cmp >= 0);
  2974.             break;
  2975.  
  2976.         case LIKE_OP:
  2977.             result = regexpTest(v1,v2,maxLen);
  2978.             break;
  2979.  
  2980.         case NOT_LIKE_OP:
  2981.             result = !(regexpTest(v1,v2,maxLen));
  2982.             break;
  2983.     }
  2984.     return(result);
  2985. }
  2986.  
  2987.  
  2988.  
  2989.  
  2990.  
  2991.  
  2992. /****************************************************************************
  2993. **     _realMatch
  2994. **
  2995. **    Purpose    : Comparison suite for real fields
  2996. **    Args    : 
  2997. **    Returns    : 
  2998. **    Notes    : 
  2999. */
  3000.  
  3001. static int realMatch(v1,v2,op)
  3002.     double    v1, 
  3003.         v2;
  3004.     int     op;
  3005. {
  3006.     int    result;
  3007.  
  3008.     switch(op)
  3009.     {
  3010.         case EQ_OP:
  3011.             result = (v1 == v2);
  3012.             break;
  3013.             
  3014.         case NE_OP:
  3015.             result = (v1 != v2);
  3016.             break;
  3017.             
  3018.         case LT_OP:
  3019.             result = (v1 < v2);
  3020.             break;
  3021.             
  3022.         case LE_OP:
  3023.             result = (v1 <= v2);
  3024.             break;
  3025.             
  3026.         case GT_OP:
  3027.             result = (v1 > v2);
  3028.             break;
  3029.             
  3030.         case GE_OP:
  3031.             result = (v1 >= v2);
  3032.             break;
  3033.     }
  3034.     return(result);
  3035. }
  3036.  
  3037.  
  3038.  
  3039.  
  3040.  
  3041.  
  3042. /****************************************************************************
  3043. **     _matchRow
  3044. **
  3045. **    Purpose    : Determine if the given row matches the required data
  3046. **    Args    : 
  3047. **    Returns    : 
  3048. **    Notes    : Used by "where" clauses
  3049. */
  3050.  
  3051. static int matchRow(cacheEntry,row,conds,clist)
  3052.     cache_t    *cacheEntry;
  3053.     u_char    *row;
  3054.     cond_t    *conds;
  3055.     int    *clist;
  3056. {
  3057.     REG     cond_t    *curCond;
  3058.     REG     char    *cp;
  3059.     REG     int    *ip,
  3060.             result,
  3061.             tmp,
  3062.             ival;
  3063.     int    *offset,
  3064.         init=1;
  3065.     double    *fp;
  3066.     char    buf[8];
  3067.     u_char    *tmpUChar;
  3068.     val_t    *value,
  3069.         tmpVal;
  3070.     field_t    *curField,
  3071.         tmpField;
  3072.     int    tmpFlist[2],
  3073.         foundField;
  3074.  
  3075.  
  3076.     msqlTrace(TRACE_IN,"matchRow()");
  3077.     result=0;
  3078.     if (!conds)
  3079.     {
  3080.         msqlTrace(TRACE_OUT,"matchRow()");
  3081.         return(1);
  3082.     }
  3083.     curCond = conds;
  3084.     offset = clist;
  3085.     while(curCond)
  3086.     {
  3087.         /*
  3088.         ** If we are comparing 2 fields (e.g. in a join) then
  3089.         ** grab the value of the second field so that we can do
  3090.         ** the comparison.  Watch for type mismatches!
  3091.         */
  3092.         foundField = 0;
  3093.         switch(curCond->value->type)
  3094.         {
  3095.             case IDENT_TYPE:
  3096.             value = curCond->value;
  3097.             curField = cacheEntry->def;
  3098.             if (!*(value->val.identVal->seg1))
  3099.             {
  3100.                 if (!cacheEntry->result)
  3101.                 {
  3102.                     strcpy(value->val.identVal->seg1,
  3103.                         cacheEntry->table);
  3104.                 }
  3105.                 else
  3106.                 {
  3107.                     strcpy(errMsg,UNQUAL_ERROR);
  3108.                     msqlDebug(MOD_ERR,
  3109.                        "Unqualified field in comparison\n");
  3110.                     msqlTrace(TRACE_OUT,"matchRow()");
  3111.                     return(-1);
  3112.                 }
  3113.             }
  3114.             while(curField)
  3115.             {
  3116.                 if (strcmp(curField->table,
  3117.                     value->val.identVal->seg1) == 0 &&
  3118.                     strcmp(curField->name,
  3119.                     value->val.identVal->seg2) == 0)
  3120.                 {
  3121.                     (void)bcopy(curField,&tmpField,
  3122.                         sizeof(field_t));
  3123.                     tmpField.value=NULL;
  3124.                     tmpField.next = NULL;
  3125.                     setupFields(cacheEntry,tmpFlist,
  3126.                         &tmpField,NULL);
  3127.                     extractValues(row,&tmpField,tmpFlist);
  3128.                     (void)bcopy(tmpField.value,&tmpVal,
  3129.                         sizeof(val_t));
  3130.                     if (tmpVal.type == CHAR_TYPE)
  3131.                     {
  3132.                         tmpVal.val.charVal= (u_char*)malloc
  3133.                         (curField->length + 1);
  3134.                         bcopy(tmpField.value->val.charVal,
  3135.                         tmpVal.val.charVal,
  3136.                         curField->length);
  3137.                     }
  3138.                     freeValue(tmpField.value);
  3139.                     tmpField.value = NULL;
  3140.                     value = &tmpVal;
  3141.                     foundField = 1;
  3142.                     break;
  3143.                 }
  3144.                 curField=curField->next;
  3145.             }
  3146.             if (!foundField)
  3147.             {
  3148.                 sprintf(errMsg,BAD_FIELD_ERROR,
  3149.                     value->val.identVal->seg1,
  3150.                     value->val.identVal->seg2);
  3151.                 msqlDebug(MOD_ERR,"Unknown field '%s.%s'\n",
  3152.                     value->val.identVal->seg1,
  3153.                     value->val.identVal->seg2);
  3154.                 msqlTrace(TRACE_OUT,"matchRow()");
  3155.                 (void)free(value->val.charVal);
  3156.                 return(-1);
  3157.             }
  3158.             break;
  3159.  
  3160.             case INT_TYPE:
  3161.             case REAL_TYPE:
  3162.             case CHAR_TYPE:
  3163.             default:
  3164.             value = curCond->value;
  3165.             break;
  3166.         }
  3167.  
  3168.  
  3169.         /*
  3170.         ** Ensure that the comparison is with the correct type.
  3171.         ** We can't do this in setupConds() as we have to wait
  3172.         ** for the evaluation of field to field comparisons.  We
  3173.         ** also fudge it for real/int comparisons.
  3174.         */
  3175.  
  3176.         if (value->nullVal)
  3177.         {
  3178.             value->type = curCond->type;
  3179.         }
  3180.         if (curCond->type == REAL_TYPE  && value->type == INT_TYPE)
  3181.         {
  3182.             value->val.realVal = value->val.intVal;
  3183.             value->type = REAL_TYPE;
  3184.         }
  3185.         if (curCond->type != value->type)
  3186.         {
  3187.             sprintf(errMsg,BAD_TYPE_ERROR, curCond->name);
  3188.             msqlDebug(MOD_ERR,"Bad type for comparison of '%s'",
  3189.                 curCond->name);
  3190.             return(-1);
  3191.         }
  3192.  
  3193.  
  3194.         /*
  3195.         ** O.K. do the actual comparison
  3196.         */
  3197.         switch(curCond->type)
  3198.         {
  3199.             case INT_TYPE:
  3200.                 if (value->nullVal)
  3201.                 {
  3202. #ifndef _CRAY
  3203.                     tmp = intMatch(*(row + *offset),0,
  3204.                         curCond->op);
  3205. #else
  3206.                     tmp = intMatch(ival, 0, curCond->op);
  3207. #endif
  3208.                     break;
  3209.                 }
  3210. #ifdef _CRAY
  3211.                 ival = unpackInt32(row + *offset + 1);
  3212. #else
  3213.  
  3214.                 (void)bcopy((row + *offset +1),buf,sizeof(int));
  3215.                 ip = (int*)buf;
  3216. #endif
  3217.                 if (curCond->op == LIKE_OP)
  3218.                 {
  3219.                     strcpy(errMsg, INT_LIKE_ERROR);
  3220.                     msqlDebug(MOD_ERR,
  3221.                        "Can't perform LIKE on int value\n");
  3222.                     msqlTrace(TRACE_OUT,"matchRow()");
  3223.                     return(-1);
  3224.                 }
  3225. #ifndef _CRAY
  3226.                 tmp = intMatch(*ip,value->val.intVal,
  3227.                     curCond->op);
  3228. #else
  3229.                 tmp = intMatch(ival, value->val.intVal, 
  3230.                     curCond->op);
  3231. #endif
  3232.                 break;
  3233.  
  3234.             case CHAR_TYPE:
  3235.                 if (value->nullVal)
  3236.                 {
  3237.                     tmp = intMatch(*(row + *offset),0,
  3238.                         curCond->op);
  3239.                     break;
  3240.                 }
  3241.                 cp = (char *)row + *offset +1;
  3242.                 tmp = charMatch(cp,value->val.charVal,
  3243.                     curCond->op, curCond->length);
  3244.                 if (value == &tmpVal)
  3245.                 {
  3246.                     free(tmpVal.val.charVal);
  3247.                 }
  3248.                 if (tmp < 0)
  3249.                 {
  3250.                     msqlTrace(TRACE_OUT,"matchRow()");
  3251.                     return(-1);
  3252.                 }
  3253.                 break;
  3254.  
  3255.             case REAL_TYPE:
  3256.                 if (value->nullVal)
  3257.                 {
  3258.                     tmp = intMatch(*(row + *offset),0,
  3259.                         curCond->op);
  3260.                     break;
  3261.                 }
  3262.                 (void)bcopy((row + *offset +1),buf,
  3263.                     sizeof(double));
  3264.                 fp = (double *)(buf);
  3265.                 if (curCond->op == LIKE_OP)
  3266.                 {
  3267.                     strcpy(errMsg, REAL_LIKE_ERROR);
  3268.                     msqlDebug(MOD_ERR,
  3269.                       "Can't perform LIKE on real value\n");
  3270.                     msqlTrace(TRACE_OUT,"matchRow()");
  3271.                     return(-1);
  3272.                 }
  3273.                 tmp = realMatch(*fp,value->val.realVal,
  3274.                     curCond->op);
  3275.                 break;
  3276.         }
  3277.     
  3278.         if (init)
  3279.         {
  3280.             result = tmp;
  3281.             init = 0;
  3282.         }
  3283.         else
  3284.         {
  3285.             switch(curCond->bool)
  3286.             {
  3287.                 case NO_BOOL:
  3288.                     result = tmp;
  3289.                     break;
  3290.     
  3291.                 case AND_BOOL:
  3292.                     result &= tmp;
  3293.                     break;
  3294.     
  3295.                 case OR_BOOL:
  3296.                     result |= tmp;
  3297.                     break;
  3298.             }
  3299.         }
  3300.         curCond = curCond->next;
  3301.         offset++;
  3302.     }
  3303.     msqlTrace(TRACE_OUT,"matchRow()");
  3304.     return(result);
  3305. }
  3306.  
  3307.  
  3308. static int compareRows(r1,r2,order,olist)
  3309.     char    *r1,
  3310.         *r2;
  3311.     order_t    *order;
  3312.     int    *olist;
  3313. {
  3314.     REG     order_t *curOrder;
  3315.     char    buf[sizeof(double)],
  3316.         *cp1,
  3317.         *cp2;
  3318.     int    res,
  3319.         *offset,
  3320.         ip1,
  3321.         ip2,
  3322.         ival1,
  3323.         ival2;
  3324.     double    fp1,
  3325.         fp2;
  3326.  
  3327.  
  3328.     /*
  3329.     ** Allow for cases when rows are not defined
  3330.     */
  3331.     msqlTrace(TRACE_IN,"compareRows()");
  3332.     if (r1 && !r2)
  3333.     {
  3334.         msqlTrace(TRACE_OUT,"compareRows()");
  3335.         return(-1);
  3336.     }
  3337.     if (!r1 && r2)
  3338.     {
  3339.         msqlTrace(TRACE_OUT,"compareRows()");
  3340.         return(1);
  3341.     }
  3342.     if (!r1 && !r2)
  3343.     {
  3344.         msqlTrace(TRACE_OUT,"compareRows()");
  3345.         return(0);
  3346.     }
  3347.  
  3348.     /*
  3349.     ** OK, we have both rows.
  3350.     */
  3351.     curOrder = order;
  3352.     offset = olist;
  3353.     while(curOrder)
  3354.     {
  3355.         switch(curOrder->type)
  3356.         {
  3357.             case INT_TYPE:
  3358. #ifndef _CRAY
  3359.                 (void)bcopy((r1 + *offset +1),buf,sizeof(int));
  3360.                 ip1 = (int) * (int*)buf;
  3361.                 (void)bcopy((r2 + *offset +1),buf,sizeof(int));
  3362.                 ip2 = (int) * (int*)buf;
  3363.  
  3364.                 if (ip1 == ip2)
  3365.                     res = 0;
  3366.                 if (ip1 > ip2)
  3367.                     res = 1;
  3368.                 if (ip1 < ip2)
  3369.                     res = -1;
  3370. #else
  3371.                 ival1 = unpackInt32(r1 + *offset + 1);
  3372.                 ival2 = unpackInt32(r2 + *offset + 1);
  3373.  
  3374.                 if (ival1 == ival2)
  3375.                     res = 0;
  3376.                 if (ival1 > ival2)
  3377.                     res = 1;
  3378.                 if (ival1 < ival2)
  3379.                     res = -1;
  3380. #endif
  3381.                 break;
  3382.  
  3383.             case CHAR_TYPE:
  3384.                 cp1 = (char *)r1 + *offset +1;
  3385.                 cp2 = (char *)r2 + *offset +1;
  3386.                 res = strcmp(cp1,cp2);
  3387.                 break;
  3388.  
  3389.             case REAL_TYPE:
  3390.                 (void)bcopy((r1+*offset+1),buf,sizeof(double));
  3391.                 fp1 = (double) * (double *)(buf);
  3392.                 (void)bcopy((r2+*offset+1),buf,sizeof(double));
  3393.                 fp2 = (double) * (double *)(buf);
  3394.                 if (fp1 == fp2)
  3395.                     res = 0;
  3396.                 if (fp1 > fp2)
  3397.                     res = 1;
  3398.                 if (fp1 < fp2)
  3399.                     res = -1;
  3400.                 break;
  3401.         }
  3402.         if (curOrder->dir == DESC)
  3403.         {
  3404.             res = 0 - res;
  3405.         }
  3406.         if (res != 0)
  3407.         {
  3408.             msqlTrace(TRACE_OUT,"compareRows()");
  3409.             return(res);
  3410.         }
  3411.         curOrder = curOrder->next;
  3412.         offset++;
  3413.     }
  3414.     msqlTrace(TRACE_OUT,"compareRows()");
  3415.     return(0);
  3416. }
  3417.  
  3418.  
  3419.  
  3420.  
  3421. int msqlInit(DB)
  3422.     char    *DB;
  3423. {
  3424.     char    path[255];
  3425.     struct    stat buf;
  3426.     extern    char *curDB;
  3427.  
  3428.     msqlTrace(TRACE_IN,"msqlInit()");
  3429.     (void)sprintf(path,"%s/msqldb/%s",msqlHomeDir,DB);
  3430.     if (stat(path,&buf) < 0)
  3431.     {
  3432.         sprintf(errMsg,BAD_DB_ERROR,DB);
  3433.         msqlDebug(MOD_ERR,"Unknown database \"%s\"\n",DB);
  3434.         msqlTrace(TRACE_OUT,"msqlInit()");
  3435.         return(-1);
  3436.     }
  3437.     msqlTrace(TRACE_OUT,"msqlInit()");
  3438.     return(0);
  3439. }
  3440.  
  3441.  
  3442.  
  3443. int msqlCreate(table,fields,DB)
  3444.     char    *table;
  3445.     field_t    *fields;
  3446.     char    *DB;
  3447. {
  3448.     char    defPath[255],
  3449.         datPath[255],
  3450.         line[80];
  3451.     field_t    *curField;
  3452.     int    fd,
  3453.         rem,
  3454.         fieldCount,
  3455.         foundKey;
  3456.  
  3457.     msqlTrace(TRACE_IN,"msqlCreate()");
  3458.  
  3459.     /*
  3460.     ** Write the catalog entry
  3461.     */
  3462.     (void)sprintf(defPath,"%s/msqldb/%s/%s.def",msqlHomeDir,DB,table);
  3463.     fd = open(defPath,O_RDONLY,0);
  3464.     if (fd >= 0)
  3465.     {
  3466.         (void)close(fd);
  3467.         sprintf(errMsg,TABLE_EXISTS_ERROR,table);
  3468.         msqlDebug(MOD_ERR,"Table \"%s\" exists\n",table);
  3469.         msqlTrace(TRACE_OUT,"msqlCreate()");
  3470.         return(-1);
  3471.     }
  3472.     fd = open(defPath,O_WRONLY | O_CREAT, 0600);
  3473.     if (fd < 0)
  3474.     {
  3475.         sprintf(errMsg,TABLE_FAIL_ERROR,table);
  3476.         msqlDebug(MOD_ERR,"Can't create table \"%s\"\n",table);
  3477.         msqlTrace(TRACE_OUT,"msqlCreate()");
  3478.         return(-1);
  3479.     }
  3480.     
  3481.     /*
  3482.     ** Ensure that there aren't too many fields
  3483.     */
  3484.     curField = fields;
  3485.     fieldCount = foundKey = 0;
  3486.     while(curField)
  3487.     {
  3488.         (void)strcpy(curField->table,table);
  3489.         fieldCount++;
  3490.         if (curField->flags & PRI_KEY_FLAG)
  3491.         {
  3492.             foundKey = 1;
  3493.         }
  3494.         curField = curField->next;
  3495.     }
  3496.     if (fieldCount > MAX_FIELDS)
  3497.     {
  3498.         sprintf(errMsg,TABLE_WIDTH_ERROR,MAX_FIELDS);
  3499.         msqlDebug(MOD_ERR,"Too many fields in table (%d Max)\n",MAX_FIELDS);
  3500.         msqlTrace(TRACE_OUT,"msqlCreate()");
  3501.         return(-1);
  3502.     }
  3503.  
  3504.     /*
  3505.     ** Dump the field definition to the table def file
  3506.     */
  3507.     curField = fields;
  3508.     while(curField)
  3509.     {
  3510.         if(write(fd,curField,sizeof(field_t)) <0)
  3511.         {
  3512.             (void)close(fd);
  3513.             unlink(defPath);
  3514.             sprintf(errMsg,CATALOG_WRITE_ERROR);
  3515.             msqlDebug(MOD_ERR,"Error writing catalog\n");
  3516.             msqlTrace(TRACE_OUT,"msqlCreate()");
  3517.             return(-1);
  3518.         }
  3519.         curField = curField->next;
  3520.     }
  3521.     (void)close(fd);
  3522.  
  3523.     /*
  3524.     ** If there was a key field, create the key file
  3525.     */
  3526.     if (foundKey)
  3527.     {
  3528.         (void)sprintf(defPath,"%s/msqldb/%s/%s.key",msqlHomeDir,DB,table);
  3529.         fd = open(defPath, O_CREAT|O_RDWR, 0600);
  3530.         if (fd < 0)
  3531.         {
  3532.             sprintf(errMsg,KEY_CREATE_ERROR);
  3533.             msqlDebug(MOD_ERR,"Creation of key table failed!\n");
  3534.             msqlTrace(TRACE_OUT,"msqlCreate()");
  3535.             return(-1);
  3536.         }
  3537.         close(fd);
  3538.     }
  3539.  
  3540.  
  3541.     /*
  3542.     ** Create an empty table
  3543.     */
  3544.     
  3545.     (void)sprintf(datPath,"%s/msqldb/%s/%s.dat",msqlHomeDir,DB,table);
  3546.     (void)unlink(datPath);
  3547.     fd = open(datPath,O_CREAT | O_WRONLY, 0600);
  3548.     if (fd < 0)
  3549.     {
  3550.         unlink(datPath);
  3551.         unlink(defPath);
  3552.         sprintf(errMsg,DATA_FILE_ERROR,table);
  3553.         msqlDebug(MOD_ERR,"Error creating table file for \"%s\"\n",table);
  3554.         msqlTrace(TRACE_OUT,"msqlCreate()");
  3555.         return(-1);
  3556.     }
  3557.     close(fd);
  3558.     sprintf(packet,"1:\n");
  3559.     writePkt(outSock);
  3560.     msqlTrace(TRACE_OUT,"msqlCreate()");
  3561.     return(0);
  3562. }
  3563.  
  3564.  
  3565. int msqlDrop(table,DB)
  3566.     char    *table,
  3567.         *DB;
  3568. {
  3569.     char    path[255];
  3570.     FILE    *fp;
  3571.     REG     cache_t *entry;
  3572.     REG     int    count;
  3573.  
  3574.     msqlTrace(TRACE_IN,"msqlDrop()");
  3575.  
  3576.     /* 
  3577.     ** Invalidate the cache entry so that we don't use it again 
  3578.     */
  3579.  
  3580.     count = 0;
  3581.     while(count < CACHE_SIZE)
  3582.     {
  3583.         entry = tableCache + count;
  3584.         if((strcmp(entry->DB,DB)==0)&&(strcmp(entry->table,table)==0))
  3585.         {
  3586.             msqlDebug(MOD_CACHE,"Clearing cache entry %d (%s:%s)\n",
  3587.                 count,DB,table);
  3588.             freeTableDef(entry->def);
  3589.             entry->def = NULL;
  3590.             *(entry->DB) = 0;
  3591.             *(entry->table) = 0;
  3592.             entry->age = 0;
  3593.             safeFree(entry->rowBuf);
  3594.             safeFree(entry->keyBuf);
  3595. #ifdef HAVE_MMAP
  3596.             if (entry->dataMap != (caddr_t) NULL)
  3597.             {
  3598.                 munmap(entry->dataMap,entry->size);
  3599.                 entry->dataMap = NULL;
  3600.                 entry->size = 0;
  3601.             }
  3602.             if (entry->keyMap != (caddr_t) NULL)
  3603.             {
  3604.                 munmap(entry->keyMap,entry->keySize);
  3605.                 entry->keyMap = NULL;
  3606.                 entry->keySize = 0;
  3607.             }
  3608. #endif
  3609.             close(entry->stackFD);
  3610.             close(entry->dataFD);
  3611.             close(entry->keyFD);
  3612.             break;
  3613.         }
  3614.         count++;
  3615.     }
  3616.  
  3617.     /*
  3618.     ** Now blow away the table data ,stack file, and key files
  3619.     */
  3620.     (void)sprintf(path,"%s/msqldb/%s/%s.def",msqlHomeDir,DB,table);
  3621.     fp = fopen(path,"r");
  3622.     if (!fp)
  3623.     {
  3624.         sprintf(errMsg,BAD_TABLE_ERROR,table);
  3625.         msqlDebug(MOD_ERR,"Unknown table \"%s\"\n",table);
  3626.         msqlTrace(TRACE_OUT,"msqlDrop()");
  3627.         return(-1);
  3628.     }
  3629.     (void)fclose(fp);
  3630.     unlink(path);
  3631.     (void)sprintf(path,"%s/msqldb/%s/%s.dat",msqlHomeDir,DB,table);
  3632.     unlink(path);
  3633.     (void)sprintf(path,"%s/msqldb/%s/%s.stk",msqlHomeDir,DB,table);
  3634.     unlink(path);
  3635.     (void)sprintf(path,"%s/msqldb/%s/%s.key",msqlHomeDir,DB,table);
  3636.     unlink(path);
  3637.  
  3638.     sprintf(packet,"1:\n");
  3639.     writePkt(outSock);
  3640.     msqlTrace(TRACE_OUT,"msqlDrop()");
  3641.     return(0);
  3642. }
  3643.  
  3644.  
  3645. int msqlDelete(table,conds,DB)
  3646.     char    *table;
  3647.     cond_t    *conds;
  3648.     char    *DB;
  3649. {
  3650.     int    clist[MAX_FIELDS],
  3651.         rowLen,
  3652.         keyLen,
  3653.         useKey,
  3654.         hasKey,
  3655.         res;
  3656.     u_int    rowNum;
  3657.     char    *row,
  3658.         active;
  3659.     field_t    *curField;
  3660.     pkey_t    *key;
  3661.     cache_t    *cacheEntry;
  3662.     cond_t    *curCond;
  3663.  
  3664.  
  3665.     msqlTrace(TRACE_IN,"msqlDelete()");
  3666.     if((cacheEntry = loadTableDef(table,NULL,DB)) == NULL)
  3667.     {
  3668.         msqlTrace(TRACE_OUT,"msqlDelete()");
  3669.         return(-1);
  3670.     }
  3671.  
  3672.     /*
  3673.     ** Find the offsets of the given condition
  3674.     */
  3675.  
  3676.     qualifyConds(table,conds);
  3677.     (void)bzero(clist,MAX_FIELDS * sizeof(int));
  3678.     if (setupConds(cacheEntry,clist,conds,&key) < 0)
  3679.     {
  3680.         msqlTrace(TRACE_OUT,"msqlDelete()");
  3681.         return(-1);
  3682.     }
  3683.  
  3684.     if (initTable(cacheEntry,FULL_REMAP) < 0)
  3685.     {
  3686.         msqlTrace(TRACE_OUT,"msqlDelete()");
  3687.         return(-1);
  3688.     }
  3689.  
  3690.  
  3691.     /*
  3692.     ** If the data is keyed just grab the row
  3693.     */
  3694.  
  3695.     useKey = 0;
  3696.     if (key)
  3697.     {
  3698.         if (key->op == EQ_OP)
  3699.         {
  3700.             useKey = 1;
  3701.             curCond = conds;
  3702.             while(curCond)
  3703.             {
  3704.                 if (curCond->bool == OR_BOOL)
  3705.                 {
  3706.                     useKey = 0;
  3707.                     break;
  3708.                 }
  3709.                 curCond = curCond->next;
  3710.             }
  3711.         }
  3712.     }
  3713.  
  3714.     rowLen = cacheEntry->rowLen;
  3715.     keyLen = cacheEntry->keyLen;
  3716.     if (useKey)
  3717.     {
  3718.         rowNum = readKey(cacheEntry,key);    
  3719.         msqlDebug(MOD_KEY,"Primary Key gave row %u\n",rowNum);
  3720.         if (rowNum != NO_POS)
  3721.         {
  3722.             row = readRow(cacheEntry,&active,rowNum);
  3723.             if (!row)
  3724.             {
  3725.                 return(-1);
  3726.             }
  3727.             if (active)
  3728.             {
  3729.                 res = matchRow(cacheEntry,row,conds,clist);
  3730.                 if (res < 0)
  3731.                 {
  3732.                     return(-1);
  3733.                 }
  3734.                 if (res == 1)
  3735.                 {
  3736.                     if(deleteRow(cacheEntry,rowNum) < 0)
  3737.                     {
  3738.                            msqlTrace(TRACE_OUT,"msqlDelete()");
  3739.                         return(-1);
  3740.                     }
  3741.                     if(deleteKey(cacheEntry,rowNum) < 0)
  3742.                     {
  3743.                            msqlTrace(TRACE_OUT,"msqlDelete()");
  3744.                         return(-1);
  3745.                     }
  3746.                     pushBlankPos(cacheEntry,DB,table,
  3747.                         rowNum);
  3748.                 }
  3749.             }
  3750.         }
  3751.     }
  3752.     else
  3753.     {
  3754.         rowNum = 0;
  3755.         while((row = readRow(cacheEntry,&active,rowNum)))
  3756.         {
  3757.             if (!active)
  3758.             {
  3759.                 rowNum++;
  3760.                 continue;
  3761.             }
  3762.             res = matchRow(cacheEntry,row,conds,clist);
  3763.             if (res < 0)
  3764.             {
  3765.                 return(res);
  3766.             }
  3767.             if (res == 1)
  3768.             {
  3769.                 res = deleteRow(cacheEntry,rowNum);
  3770.                 if(res < 0)
  3771.                 {
  3772.                     msqlTrace(TRACE_OUT,"msqlDelete()");
  3773.                     return(res);
  3774.                 }
  3775.                 res = deleteKey(cacheEntry,rowNum);
  3776.                 if(res < 0)
  3777.                 {
  3778.                     msqlTrace(TRACE_OUT,"msqlDelete()");
  3779.                     return(res);
  3780.                 }
  3781.                 pushBlankPos(cacheEntry,DB,table,rowNum);
  3782.             }
  3783.             rowNum++;
  3784.         }
  3785.     }
  3786.     sprintf(packet,"1:\n");
  3787.     writePkt(outSock);
  3788.     msqlTrace(TRACE_OUT,"msqlDelete()");
  3789.     return(0);
  3790. }
  3791.  
  3792.  
  3793.  
  3794.  
  3795. int msqlInsert(table,fields,DB)
  3796.     char    *table;
  3797.     field_t    *fields;
  3798.     char    *DB;
  3799. {
  3800.     int    flist[MAX_FIELDS],
  3801.         rowLen,
  3802.         useKey;
  3803.     u_int    rowNum;
  3804.     u_char    *row;
  3805.     REG     field_t    *curField,
  3806.         *curField2;
  3807.     pkey_t    *key;
  3808.     cache_t    *cacheEntry;
  3809.  
  3810.  
  3811.     msqlTrace(TRACE_IN,"msqlInsert()");
  3812.     if((cacheEntry = loadTableDef(table,NULL,DB)) == NULL)
  3813.     {
  3814.         msqlTrace(TRACE_OUT,"msqlInsert()");
  3815.         return(-1);
  3816.     }
  3817.  
  3818.     /*
  3819.     ** Find the offsets of the given fields
  3820.     */
  3821.     qualifyFields(table,fields);
  3822.     (void)bzero(flist,MAX_FIELDS * sizeof(int));
  3823.     if (setupFields(cacheEntry,flist,fields,&key) < 0)
  3824.     {
  3825.         msqlTrace(TRACE_OUT,"msqlInsert()");
  3826.         return(-1);
  3827.     }
  3828.  
  3829.     /*
  3830.     ** Ensure that no field is listed more than once and that each
  3831.     ** field was given a value.
  3832.     */
  3833.     curField = fields;
  3834.     while(curField)
  3835.     {
  3836.         if (!curField->value)
  3837.         {
  3838.             sprintf(errMsg, NO_VALUE_ERROR, curField->name);
  3839.             msqlDebug(MOD_ERR,
  3840.                 "No value specified for field '%s'",
  3841.                 curField->name);
  3842.             msqlTrace(TRACE_OUT,"msqlInsert()");
  3843.             return(-1);
  3844.         }
  3845.         curField2 = curField;
  3846.         while(curField2)
  3847.         {
  3848.             if (curField2 == curField)
  3849.             {
  3850.                 curField2 = curField2->next;
  3851.                 continue;
  3852.             }
  3853.             if (strcmp(curField->name,curField2->name) == 0 &&
  3854.                 strcmp(curField->table,curField2->table) == 0)
  3855.             {
  3856.                 sprintf(errMsg,NON_UNIQ_ERROR, curField->name);
  3857.                 msqlDebug(MOD_ERR,"Field '%s' not unique",
  3858.                     curField->name);
  3859.                 msqlTrace(TRACE_OUT,"msqlInsert()");
  3860.                 return(-1);
  3861.             }
  3862.             curField2 = curField2->next;
  3863.         }
  3864.         curField = curField->next;
  3865.     }
  3866.  
  3867.     /*
  3868.     ** Create a blank row
  3869.     */
  3870.     rowLen = cacheEntry->rowLen;
  3871.     row = cacheEntry->rowBuf + 1;
  3872.  
  3873.     /*
  3874.     ** Find a place to put this row
  3875.     */
  3876.  
  3877.     rowNum = popBlankPos(cacheEntry,DB,table);
  3878.  
  3879.     if (initTable(cacheEntry,KEY_REMAP) < 0)
  3880.     {
  3881.         msqlTrace(TRACE_OUT,"msqlInsert()");
  3882.         return(-1);
  3883.     }
  3884.  
  3885.     /*
  3886.     ** Check for a unique primary key if we have one.
  3887.     */
  3888.  
  3889.     if (key)
  3890.     {
  3891.         if (readKey(cacheEntry,key) != NO_POS)
  3892.         {
  3893.             sprintf(errMsg,KEY_UNIQ_ERROR, key->name);
  3894.             msqlDebug(MOD_ERR,"Non unique key value in field '%s'\n",
  3895.                 key->name);
  3896.             msqlTrace(TRACE_OUT,"msqlInsert()");
  3897.             return(-1);
  3898.         }
  3899.     }
  3900.  
  3901.     /*
  3902.     ** Fill in the given fields and dump it to the table file
  3903.     */
  3904.  
  3905.     (void)bzero(row,rowLen);
  3906.     fillRow(row,fields,flist);
  3907.     if (checkNullFields(cacheEntry,row) < 0)
  3908.     {
  3909.         msqlTrace(TRACE_OUT,"msqlInsert()");
  3910.         return(-1);
  3911.     }
  3912.     if(writeRow(cacheEntry,NULL,rowNum) < 0)
  3913.     {
  3914.         sprintf(errMsg,"Error on data write");
  3915.         msqlDebug(MOD_ERR,"Error on data write\n");
  3916.         msqlTrace(TRACE_OUT,"msqlInsert()");
  3917.         return(-1);
  3918.     }
  3919.     if (key)
  3920.     {
  3921.         writeKey(cacheEntry,key,rowNum);
  3922.     }
  3923.     
  3924.     sprintf(packet,"1:\n");
  3925.     writePkt(outSock);
  3926.     msqlTrace(TRACE_OUT,"msqlInsert()");
  3927.     return(0);
  3928. }
  3929.  
  3930.  
  3931.  
  3932. int msqlUpdate(table,fields,conds,DB)
  3933.     char    *table;
  3934.     field_t    *fields;
  3935.     cond_t    *conds;
  3936.     char    *DB;
  3937. {
  3938.     int    flist[MAX_FIELDS],
  3939.         clist[MAX_FIELDS],
  3940.         rowLen,
  3941.         useKey,
  3942.         res;
  3943.     u_int    rowNum;
  3944.     char    *row,
  3945.         active;
  3946.     field_t    *curField;
  3947.     pkey_t    *keyCond,
  3948.         *keyField;
  3949.     cond_t    *curCond;
  3950.     cache_t    *cacheEntry;
  3951.     
  3952.  
  3953.  
  3954.     msqlTrace(TRACE_IN,"msqlUpdate()");
  3955.     if((cacheEntry = loadTableDef(table,NULL,DB)) == NULL)
  3956.     {
  3957.         msqlTrace(TRACE_OUT,"msqlUpdate()");
  3958.         return(-1);
  3959.     }
  3960.  
  3961.     /*
  3962.     ** Find the offsets of the given fields and condition
  3963.     */
  3964.     qualifyFields(table,fields);
  3965.     qualifyConds(table,conds);
  3966.     (void)bzero(flist,MAX_FIELDS * sizeof(int));
  3967.     if (setupFields(cacheEntry,flist,fields,&keyField) < 0)
  3968.     {
  3969.         msqlTrace(TRACE_OUT,"msqlUpdate()");
  3970.         return(-1);
  3971.     }
  3972.     (void)bzero(clist,MAX_FIELDS * sizeof(int));
  3973.     if (setupConds(cacheEntry,clist,conds,&keyCond) < 0)
  3974.     {
  3975.         msqlTrace(TRACE_OUT,"msqlUpdate()");
  3976.         return(-1);
  3977.     }
  3978.  
  3979.     rowLen = cacheEntry->rowLen;
  3980.  
  3981.     if (initTable(cacheEntry,FULL_REMAP) < 0)
  3982.     {
  3983.         msqlTrace(TRACE_OUT,"msqlUpdate()");
  3984.         return(-1);
  3985.     }
  3986.  
  3987.     /*
  3988.     ** If the data is keyed just grab the row
  3989.     */
  3990.  
  3991.     useKey = 0;
  3992.     if (keyCond)
  3993.     {
  3994.         if (keyCond->op == EQ_OP)
  3995.         {
  3996.             useKey = 1;
  3997.             curCond = conds;
  3998.             while(curCond)
  3999.             {
  4000.                 if (curCond->bool == OR_BOOL)
  4001.                 {
  4002.                     useKey = 0;
  4003.                     break;
  4004.                 }
  4005.                 curCond = curCond->next;
  4006.             }
  4007.         }
  4008.     }
  4009.  
  4010.     if (useKey)
  4011.     {
  4012.         rowNum = readKey(cacheEntry,keyCond);    
  4013.         msqlDebug(MOD_KEY,"Primary Key gave row %u\n",rowNum);
  4014.         if (rowNum != NO_POS)
  4015.         {
  4016.             row = readRow(cacheEntry,&active,rowNum);
  4017.             if (active)
  4018.             {
  4019.                 res = matchRow(cacheEntry,row,conds,clist);
  4020.                 if (res < 0)
  4021.                 {
  4022.                     return(-1);
  4023.                 }
  4024.                 if (res == 1)
  4025.                 {
  4026.                     updateValues(row,fields,flist);
  4027.                     if (checkNullFields(cacheEntry,row) < 0)
  4028.                     {
  4029.                            msqlTrace(TRACE_OUT,
  4030.                             "msqlUpdate()");
  4031.                         return(-1);
  4032.                     }
  4033.                     if(writeRow(cacheEntry,row,rowNum) < 0)
  4034.                     {
  4035.                         sprintf(errMsg,WRITE_ERROR);
  4036.                         msqlDebug(MOD_ERR,
  4037.                                "Error on data write\n");
  4038.                            msqlTrace(TRACE_OUT,
  4039.                             "msqlUpdate()");
  4040.                         return(-1);
  4041.                     }
  4042.                     if (keyField)
  4043.                     {
  4044.                         curField = fields;
  4045.                         while(curField)
  4046.                         {
  4047.                         if(curField->flags&PRI_KEY_FLAG)
  4048.                         {
  4049.                             freeValue(
  4050.                                 keyField->value);
  4051.                             keyField->value =
  4052.                                 curField->value;
  4053.                             writeKey(cacheEntry,
  4054.                                 keyField,
  4055.                                 rowNum);
  4056.  
  4057.                             break;
  4058.                         }
  4059.                         curField=curField->next;
  4060.                         }
  4061.                     }
  4062.                 }
  4063.             }
  4064.         }
  4065.     }
  4066.     else
  4067.     {
  4068.         rowNum = 0;
  4069.         while((row = readRow(cacheEntry,&active,rowNum)))
  4070.         {
  4071.             if (!active)
  4072.             {
  4073.                 rowNum++;
  4074.                 continue;
  4075.             }
  4076.             res = matchRow(cacheEntry,row,conds,clist);
  4077.             if (res < 0)
  4078.             {
  4079.                 return(-1);
  4080.             }
  4081.             if (res == 1)
  4082.             {
  4083.                 updateValues(row,fields,flist);
  4084.                 if (checkNullFields(cacheEntry,row) < 0)
  4085.                 {
  4086.                     msqlTrace(TRACE_OUT,"msqlUpdate()");
  4087.                     return(-1);
  4088.                 }
  4089.                 if(writeRow(cacheEntry,row,rowNum) < 0)
  4090.                 {
  4091.                     sprintf(errMsg,WRITE_ERROR);
  4092.                     msqlDebug(MOD_ERR,"Error on data write\n");
  4093.                     msqlTrace(TRACE_OUT,"msqlUpdate()");
  4094.                     return(-1);
  4095.                 }
  4096.                 if (keyField)
  4097.                 {
  4098.                     curField = fields;
  4099.                     while(curField)
  4100.                     {
  4101.                         if(curField->flags&PRI_KEY_FLAG)
  4102.                         {
  4103.                             freeValue(
  4104.                                 keyField->value);
  4105.                             keyField->value =
  4106.                                 curField->value;
  4107.                             writeKey(cacheEntry,
  4108.                                 keyField,
  4109.                                 rowNum);
  4110.                         }
  4111.                         curField=curField->next;
  4112.                     }
  4113.                 }
  4114.             }
  4115.             rowNum++;
  4116.         }
  4117.     }
  4118.     sprintf(packet,"1:\n");
  4119.     writePkt(outSock);
  4120.     msqlTrace(TRACE_OUT,"msqlUpdate()");
  4121.     return(0);
  4122. }
  4123.  
  4124.  
  4125. static void formatPacket(packet,fields)
  4126.     char    *packet;
  4127.     field_t    *fields;
  4128. {
  4129.     char    outBuf[100],
  4130.         bufLen[4];
  4131.     u_char    *outData;
  4132.     field_t    *curField;
  4133.  
  4134.     msqlTrace(TRACE_IN,"formatPacket()");
  4135.     curField = fields;
  4136.     while(curField)
  4137.     {
  4138.         if (!curField->value->nullVal)
  4139.         {
  4140.             switch(curField->type)
  4141.             {
  4142.                 case INT_TYPE:
  4143.                     sprintf(outBuf,"%d",
  4144.                         curField->value->val.intVal);
  4145.                     outData = (u_char *)outBuf;
  4146.                     break;
  4147.                 case CHAR_TYPE:
  4148.                     outData = curField->value->val.charVal;
  4149.                     break;
  4150.                 case REAL_TYPE:
  4151.                     /* Analogy Start */
  4152.                     sprintf(outBuf,"%g",
  4153.                         curField->value->val.realVal);
  4154.                     /* Analogy End */
  4155.                     outData = (u_char *)outBuf;
  4156.                     break;
  4157.             }
  4158.             sprintf(bufLen,"%d:",strlen(outData));
  4159.             strcat(packet,bufLen);
  4160.             strcat(packet,outData);
  4161.         }
  4162.         else
  4163.         {
  4164.             strcat(packet,"-1:");
  4165.         }
  4166.         curField = curField->next;
  4167.     }
  4168.     strcat(packet,"\n");
  4169.     msqlTrace(TRACE_OUT,"formatPacket()");
  4170. }
  4171.  
  4172.  
  4173.  
  4174. static void mergeRows(row,table1,t1Row,table2,t2Row)
  4175.     char    *row,
  4176.         *t1Row,
  4177.         *t2Row;
  4178.     cache_t    *table1,
  4179.         *table2;
  4180. {
  4181.     (void)bcopy(t1Row,row,table1->rowLen);
  4182.     (void)bcopy(t2Row,row+table1->rowLen,table2->rowLen);
  4183. }
  4184.  
  4185.  
  4186. static field_t *createTmpFieldCopy(field)
  4187.     field_t *field;
  4188. {
  4189.     static    field_t new;
  4190.  
  4191.     bcopy(field,&new,sizeof(new));
  4192.     new.next = NULL;
  4193.     new.value = NULL;
  4194.     return(&new);
  4195. }
  4196.  
  4197. static field_t *getFieldByName(name,def,offset)
  4198.     char    *name;
  4199.     field_t    *def;
  4200.     int    *offset;
  4201. {
  4202.     field_t    *cur;
  4203.  
  4204.     cur = def;
  4205.     offset = 0;
  4206.     while(cur)
  4207.     {
  4208.         if (strcmp(cur->name,name) == 0)
  4209.             break;
  4210.         offset += cur->length;
  4211.         cur = cur->next;
  4212.     }
  4213.     if (!cur)
  4214.     {    
  4215.         return(NULL);
  4216.     }
  4217.     return(createTmpFieldCopy(cur));
  4218. }
  4219.  
  4220.  
  4221. static int checkForPartialMatch(conds)
  4222.     cond_t    *conds;
  4223. {
  4224.     cond_t    *curCond;
  4225.     int    res;
  4226.     
  4227.     res = 1;
  4228.     curCond = conds;
  4229.     while(curCond)
  4230.     {
  4231.         if (curCond->value->type == IDENT)
  4232.         {
  4233.             res = 0;
  4234.         }
  4235.         if (curCond->bool == OR_BOOL)
  4236.         {
  4237.             return(0);
  4238.         }
  4239.         curCond=curCond->next;
  4240.     }
  4241.     return(res);
  4242. }
  4243.  
  4244.  
  4245.  
  4246. static cache_t *joinTables(table1,table2,conds,DB)
  4247.     cache_t    *table1,
  4248.         *table2;
  4249.     cond_t    *conds;
  4250.     char    *DB;
  4251. {
  4252.     cache_t    *tmpTable,
  4253.         *curTable,
  4254.         *outer,
  4255.         *inner;
  4256.     int    addCond,
  4257.         doRowMatch = 1,
  4258.         addPartial,
  4259.         oRowNum,
  4260.         iRowNum,
  4261.         clist[MAX_FIELDS],
  4262.         outerClist[MAX_FIELDS],
  4263.         res;
  4264.     cond_t    *newCondHead,     *newCondTail,
  4265.         *t1CondHead,     *t1CondTail,
  4266.         *t2CondHead,     *t2CondTail,
  4267.         *outerConds,
  4268.         *newCond,
  4269.         *curCond,
  4270.         *keyCond;
  4271.     field_t    *curField,
  4272.         *tmpField,
  4273.         *keyField;
  4274.     char    *oRow,
  4275.         *iRow,
  4276.         active;
  4277.     u_char    *row;
  4278.     pkey_t    *key,
  4279.         *outerKey;
  4280.  
  4281.  
  4282.         msqlTrace(TRACE_IN,"joinTables()");
  4283.  
  4284.     /*
  4285.     ** Create a condition list for all conditions that relate
  4286.     ** to the newly created result table.  All we have to do is
  4287.     ** look for a result table entry from the same original
  4288.     ** table as the condition field as all table fields are
  4289.     ** merged into the result.
  4290.     **
  4291.     ** Also create condition lists for each source table so we
  4292.     ** can do partial match optimisation on the outer loop.
  4293.     */
  4294.     t1CondHead = t2CondHead = newCondHead = NULL;
  4295.     curCond = conds;
  4296.     while(curCond)
  4297.     {
  4298.         addCond = 0;
  4299.         addPartial = 0;
  4300.         curTable = table1;
  4301.         curField = curTable->def;
  4302.         while(curField)
  4303.         {
  4304.         if(strcmp(curField->table,curCond->table) == 0)
  4305.         {
  4306.             if (curCond->value->type == IDENT_TYPE)
  4307.             {
  4308.             tmpField = table1->def;
  4309.             tmpTable = table1;
  4310.             while(tmpField)
  4311.             {
  4312.                 if(strcmp(tmpField->table,
  4313.                 curCond->value->val.identVal->seg1)==0 &&
  4314.                    strcmp(tmpField->name,
  4315.                 curCond->value->val.identVal->seg2)==0)
  4316.                 {
  4317.                 addCond = 1;
  4318.                 break;
  4319.                 }
  4320.                 tmpField = tmpField->next;
  4321.                 if (!tmpField)
  4322.                 {
  4323.                 if (tmpTable == table1)
  4324.                 {
  4325.                         tmpTable = table2;
  4326.                     tmpField = table2->def;
  4327.                 }
  4328.                 }
  4329.             }
  4330.  
  4331.             /*
  4332.             ** If we get here it's a field to field
  4333.             ** comparison between the cur field and a field
  4334.             ** in another table.  We can't try a match
  4335.             ** because we'll screw up on OR conditions!
  4336.             */
  4337.             doRowMatch = 0;
  4338.             }
  4339.             else
  4340.             {
  4341.             addCond = 1;
  4342.             addPartial = 1;
  4343.             }
  4344.             break;
  4345.         }
  4346.             curField = curField->next;
  4347.         if (!curField)
  4348.         {
  4349.             if (curTable == table1)
  4350.             {
  4351.                 curField = table2->def;
  4352.                 curTable = table2;
  4353.             }
  4354.         }
  4355.         }
  4356.         if (addCond)
  4357.         {
  4358.         newCond = (cond_t *)malloc(sizeof(cond_t));
  4359.         (void)bcopy(curCond,newCond,sizeof(cond_t));
  4360.         if (!newCondHead)
  4361.         {
  4362.             newCondHead = newCondTail = newCond;
  4363.         }
  4364.         else
  4365.         {
  4366.             newCondTail->next = newCond;
  4367.             newCondTail = newCond;
  4368.         }
  4369.         newCond->next = NULL;
  4370.          }
  4371.          if (addPartial)
  4372.          {
  4373.         if (strcmp(curCond->table, table1->table) == 0)
  4374.         {
  4375.             newCond = (cond_t *)malloc(sizeof(cond_t));
  4376.             (void)bcopy(curCond,newCond,sizeof(cond_t));
  4377.             if(!t1CondHead)
  4378.             {
  4379.                 t1CondHead = t1CondTail = newCond;
  4380.             }
  4381.             else
  4382.             {
  4383.                 t1CondTail->next = newCond;
  4384.                 t1CondTail = newCond;
  4385.             }
  4386.             newCond->next = NULL;
  4387.         }
  4388.         if (strcmp(curCond->table, table2->table) == 0)
  4389.         {
  4390.             newCond = (cond_t *)malloc(sizeof(cond_t));
  4391.             (void)bcopy(curCond,newCond,sizeof(cond_t));
  4392.             if(!t2CondHead)
  4393.             {
  4394.                 t2CondHead = t2CondTail = newCond;
  4395.             }
  4396.             else
  4397.             {
  4398.                 t2CondTail->next = newCond;
  4399.                 t2CondTail = newCond;
  4400.             }
  4401.             newCond->next = NULL;
  4402.         }
  4403.         }
  4404.         curCond = curCond->next;
  4405.     }
  4406.  
  4407.     /*
  4408.     ** See if we can do partial match optimisation on either table
  4409.     */
  4410.     outer = table1;
  4411.     inner = table2;
  4412.     outerConds = NULL;
  4413.     if (checkForPartialMatch(t1CondHead))
  4414.     {
  4415.         outerConds = t1CondHead;
  4416.         if(setupConds(table1,outerClist,outerConds,&outerKey) < 0)
  4417.         {
  4418.             return(NULL);
  4419.         }
  4420.     }
  4421.     else if(checkForPartialMatch(t2CondHead))
  4422.     {
  4423.         outer = table2;
  4424.         inner = table1;
  4425.         outerConds = t2CondHead;
  4426.         if(setupConds(table2,outerClist,outerConds,&outerKey) < 0)
  4427.         {
  4428.             return(NULL);
  4429.         }
  4430.     }
  4431.  
  4432.     /*
  4433.     ** Create a table definition for the join result.  We can't do
  4434.     ** this earlier as we mus know which is the inner and outer table
  4435.     */
  4436.     tmpTable = createTmpTable(outer,inner,NULL);
  4437.     if (!tmpTable)
  4438.     {
  4439.             msqlTrace(TRACE_OUT,"joinTables()");
  4440.         return(NULL);
  4441.     }
  4442.     (void)sprintf(tmpTable->resInfo,"'%s (%s+%s)'",tmpTable->table,
  4443.         table1->table, table2->table);
  4444.  
  4445.  
  4446.  
  4447.  
  4448.     /*
  4449.     ** See if we can use a key for the inner table
  4450.     **
  4451.     ** This gets too ugly with the current condition handling.  This
  4452.     ** can wait for the new expression based stuff in 1.1
  4453.     if (table2->keyFD > 0)
  4454.         curField = inner->def;
  4455.     else
  4456.         curField = NULL;
  4457.     keyField = NULL;
  4458.     while(curField && !keyField)
  4459.     {
  4460.             if(curField->flags & PRI_KEY_FLAG)
  4461.             {
  4462.             curCond = newCondHead;
  4463.             while(curCond)
  4464.             {
  4465.                 if(strcmp(curField->table,curCond->table) == 0 
  4466.                    &&strcmp(curField->name,curCond->name) == 0)
  4467.                 {
  4468.                     keyField = curField;
  4469.                     keyCond = curCond;
  4470.                 }
  4471.  
  4472.                 if (curCond->type == IDENT_TYPE)
  4473.                 {
  4474.                     if(!strcmp(curField->table,
  4475.                         curCond->val.identVal->seg1)
  4476.                          &&!strcmp(curField->name,
  4477.                         curCond->val.identVal->seg2))
  4478.                     {
  4479.                         keyVal = 
  4480.                     }
  4481.                 }
  4482.                 curCond = curCond->next;
  4483.             }
  4484.         }
  4485.         curField = curField->next;
  4486.     }
  4487.     *
  4488.     */
  4489.  
  4490.     /*
  4491.     ** Do an N Squared join of the tables
  4492.     */
  4493.  
  4494.     row = tmpTable->rowBuf;
  4495.     if (setupConds(tmpTable,clist,newCondHead,&key) < 0)
  4496.     {
  4497.             msqlTrace(TRACE_OUT,"joinTables()");
  4498.         return(NULL);
  4499.     }
  4500.     oRowNum = 0;
  4501.     while((oRow = readRow(outer,&active,oRowNum++) ))
  4502.     {
  4503.         /*
  4504.         ** Dodge holes 
  4505.         */
  4506.         if (!active)
  4507.             continue;
  4508.  
  4509.         /* 
  4510.         ** Partial match optimisation 
  4511.         */
  4512.         if(outerConds)
  4513.         {
  4514.             if (matchRow(outer,oRow,outerConds,outerClist)!=1)
  4515.             {
  4516.                 continue;
  4517.             }
  4518.         }
  4519.  
  4520.         /*
  4521.         ** Go ahead and join this row with the inner table
  4522.         */
  4523.  
  4524.         /*
  4525.         **
  4526.         if (keyField)
  4527.         {
  4528.             if (keyCond->type == IDENT_TYPE)
  4529.             {
  4530.                 extractValues(oRow,
  4531.             }
  4532.         }
  4533.         **
  4534.         */
  4535.         iRowNum = 0;
  4536.         while((iRow = readRow(inner,&active,iRowNum++) ))
  4537.         {
  4538.             if (!active)
  4539.                 continue;
  4540.             *row = 1;
  4541.             mergeRows(row+1,outer,oRow,inner,iRow);
  4542.             if (doRowMatch)
  4543.             {
  4544.                 res=matchRow(tmpTable,row+1,newCondHead,
  4545.                     clist);
  4546.             }
  4547.             else
  4548.             {
  4549.                 res = 1;
  4550.             }
  4551.             if (res < 0)
  4552.             {
  4553.                     msqlTrace(TRACE_OUT,"joinTables()");
  4554.                 return(NULL);
  4555.             }
  4556.             if (res == 1)
  4557.             {
  4558.                 if(writeRow(tmpTable,NULL,NO_POS) < 0)
  4559.                 {
  4560.                         msqlTrace(TRACE_OUT,
  4561.                         "joinTables()");
  4562.                     freeTmpTable(tmpTable);
  4563.                     return(NULL);
  4564.                 }
  4565.             }
  4566.         }
  4567.     }
  4568.  
  4569.     /*
  4570.     ** Free up the space allocated to the new condition list.
  4571.     ** We don't need to free the value structs as we just copied
  4572.     ** the pointers to them.  They'll be freed during msqlClen();
  4573.     */
  4574.     curCond = newCondHead;
  4575.     while(curCond)
  4576.     {
  4577.                 newCond = curCond;
  4578.                 curCond = curCond->next;
  4579.                 (void)free(newCond);
  4580.     }
  4581.     curCond = t1CondHead;
  4582.     while(curCond)
  4583.     {
  4584.                 newCond = curCond;
  4585.                 curCond = curCond->next;
  4586.                 (void)free(newCond);
  4587.     }
  4588.     curCond = t2CondHead;
  4589.     while(curCond)
  4590.     {
  4591.                 newCond = curCond;
  4592.                 curCond = curCond->next;
  4593.                 (void)free(newCond);
  4594.     }
  4595.     msqlTrace(TRACE_OUT,"joinTables()");
  4596.     return(tmpTable);
  4597. }
  4598.  
  4599.  
  4600.  
  4601. char *dupRow(entry,row)
  4602.     cache_t    *entry;
  4603.     char     *row;
  4604. {
  4605.     char    *new;
  4606.  
  4607.     new = (char *)malloc(entry->rowLen);
  4608.     (void)bcopy(row,new,entry->rowLen);
  4609.     return(new);
  4610. }
  4611.  
  4612.  
  4613.  
  4614. cache_t *createSortedTable(entry,order)
  4615.     cache_t    *entry;
  4616.     order_t    *order;
  4617. {
  4618.     cache_t    *new;
  4619.     field_t    *curField;
  4620.     char    *row,
  4621.         *cur = NULL,
  4622.         *last,
  4623.         active;
  4624.     u_int    rowNum,
  4625.         numRows,
  4626.         curRowNum;
  4627.     int    flist[MAX_FIELDS],
  4628.         olist[MAX_FIELDS];
  4629.     
  4630.         msqlTrace(TRACE_IN,"createSortedTable()");
  4631.     new = createTmpTable(entry,NULL,NULL);
  4632.     if (!new)
  4633.     {
  4634.             msqlTrace(TRACE_OUT,"createSortedTable()");
  4635.         return(NULL);
  4636.     }
  4637.     (void)sprintf(new->resInfo,"'%s (ordered %s)'",new->table,entry->table);
  4638.     if(initTable(entry,FULL_REMAP) < 0)
  4639.     {
  4640.             msqlTrace(TRACE_OUT,"createSortedTable()");
  4641.         return(NULL);
  4642.     }
  4643.     if (setupOrder(entry,olist,order) < 0)
  4644.     {
  4645.             msqlTrace(TRACE_OUT,"createSortedTable()");
  4646.         return(NULL);
  4647.     }
  4648.     if (setupFields(entry,flist,entry->def,NULL) < 0)
  4649.     {
  4650.             msqlTrace(TRACE_OUT,"createSortedTable()");
  4651.         return(NULL);
  4652.     }
  4653.  
  4654.  
  4655.     numRows = 1;
  4656.     last = NULL;
  4657.     while(numRows > 0)
  4658.     {
  4659.         rowNum = 0;
  4660.         numRows = 0;
  4661.         cur = NULL;
  4662.         while((row = readRow(entry,&active,rowNum)))
  4663.         {
  4664.             if (!active)
  4665.             {
  4666.                 rowNum++;
  4667.                 continue;
  4668.             }
  4669.             numRows ++;
  4670.             if (!cur)
  4671.             {
  4672. #ifdef HAVE_MMAP
  4673.                 cur = row;
  4674. #else
  4675.                 if (cur)
  4676.                     (void)free(cur);
  4677.                 cur = dupRow(entry,row);
  4678. #endif
  4679.                 curRowNum = rowNum;
  4680.                 rowNum++;
  4681.                 continue;
  4682.             }
  4683.             if (compareRows(cur,row,order,olist) >= 0)
  4684.             {
  4685.                 if (compareRows(last,row,order,olist) <= 0 ||
  4686.                     !last)
  4687.                 {
  4688. #ifdef HAVE_MMAP
  4689.                     cur = row;
  4690. #else
  4691.                     if (cur)
  4692.                         (void)free(cur);
  4693.                     cur = dupRow(entry,row);
  4694. #endif
  4695.                     curRowNum = rowNum;
  4696.                 }
  4697.             }
  4698.             rowNum++;
  4699.         }
  4700.         if (cur)
  4701.         {
  4702.             extractValues(cur,new->def,flist);
  4703.             (void)bzero((char*)(new->rowBuf+1),new->rowLen);
  4704.             fillRow(new->rowBuf + 1, new->def, flist);
  4705.             writeRow(new,NULL,NO_POS);
  4706.             deleteRow(entry,curRowNum);
  4707.             curField = new->def;
  4708.             while(curField)
  4709.             {
  4710.                 freeValue(curField->value);
  4711.                 curField->value = NULL;
  4712.                 curField = curField->next;
  4713.             }
  4714. #ifdef HAVE_MMAP
  4715.             last = cur;
  4716. #else
  4717.             if (last)
  4718.             {
  4719.                 (void)free(last);
  4720.             }
  4721.             last = dupRow(entry,cur);
  4722. #endif
  4723.         }
  4724.     }
  4725.            msqlTrace(TRACE_OUT,"createSortedTable()");
  4726.     return(new);
  4727. }
  4728.  
  4729.  
  4730.  
  4731. int createDistinctTable(entry)
  4732.     cache_t    *entry;
  4733. {
  4734.     char    *row,
  4735.         *cur = NULL,
  4736.         active;
  4737.     u_int    rowNum,
  4738.         curRowNum;
  4739.     int    flist[MAX_FIELDS];
  4740.     
  4741.  
  4742.     if(initTable(entry,FULL_REMAP) < 0)
  4743.     {
  4744.         return(-1);
  4745.     }
  4746.     if (setupFields(entry,flist,entry->def,NULL) < 0)
  4747.     {
  4748.         return(-1);
  4749.     }
  4750.  
  4751.  
  4752.     curRowNum = 0;
  4753.     while((row = readRow(entry,&active,curRowNum)))
  4754.     {
  4755.         if (!active)
  4756.         {
  4757.             curRowNum++;
  4758.             continue;
  4759.         }
  4760. #ifdef HAVE_MMAP
  4761.         cur = row;
  4762. #else
  4763.         if (cur)
  4764.             (void)free(cur);
  4765.         cur = dupRow(entry,row);
  4766. #endif
  4767.         rowNum = 0;
  4768.         while((row = readRow(entry,&active,rowNum)))
  4769.         {
  4770.             if (!active)
  4771.             {
  4772.                 rowNum++;
  4773.                 continue;
  4774.             }
  4775.             if (rowNum == curRowNum)
  4776.             {
  4777.                 rowNum++;
  4778.                 continue;
  4779.             }
  4780.  
  4781.             if (bcmp(cur,row,entry->rowLen) == 0)
  4782.             {
  4783.                 deleteRow(entry,rowNum);
  4784.             }
  4785.             rowNum++;
  4786.         }
  4787.         curRowNum++;
  4788.     }
  4789. }
  4790.  
  4791.  
  4792.  
  4793.  
  4794. static int doSelect(cacheEntry, tables, fields,conds,dest,tmpTable)
  4795.     cache_t    *cacheEntry;
  4796.     tname_t    *tables;
  4797.     field_t    *fields;
  4798.     cond_t    *conds;
  4799.     int    dest;
  4800.     cache_t    *tmpTable;
  4801. {
  4802.     int    flist[MAX_FIELDS],
  4803.         clist[MAX_FIELDS],
  4804.         tmpFlist[MAX_FIELDS],
  4805.         rowLen,
  4806.         rowNum,
  4807.         numFields,
  4808.         res;
  4809.     char    *row,
  4810.         active,
  4811.         useKey,
  4812.         outBuf[100];
  4813.     cond_t    *curCond;
  4814.     pkey_t    *key;
  4815.     REG     field_t *curField;
  4816.  
  4817.  
  4818.     msqlTrace(TRACE_IN,"doSelect()");
  4819.  
  4820.     fieldHead = fields;
  4821.     
  4822.     numFields = 0;
  4823.     curField = fieldHead;
  4824.     while(curField)
  4825.     {
  4826.         numFields++;
  4827.         curField = curField->next;
  4828.     }
  4829.  
  4830.     /*
  4831.     ** Find the offsets of the given fields and condition
  4832.     */
  4833.     (void)bzero(flist,MAX_FIELDS * sizeof(int));
  4834.     if (setupFields(cacheEntry,flist,fields,&key) < 0)
  4835.     {
  4836.         msqlTrace(TRACE_OUT,"doSelect()");
  4837.         return(-1);
  4838.     }
  4839.     (void)bzero(clist,MAX_FIELDS * sizeof(int));
  4840.     if (setupConds(cacheEntry,clist,conds,&key) < 0)
  4841.     {
  4842.         msqlTrace(TRACE_OUT,"doSelect()");
  4843.         return(-1);
  4844.     }
  4845.  
  4846.     if (tmpTable)
  4847.     {
  4848.         (void)bzero(tmpFlist,MAX_FIELDS * sizeof(int));
  4849.         if (setupFields(tmpTable,tmpFlist,fields,NULL) < 0)
  4850.         {
  4851.             msqlTrace(TRACE_OUT,"doSelect()");
  4852.             return(-1);
  4853.         }
  4854.     }
  4855.  
  4856.     rowLen = cacheEntry->rowLen;
  4857.  
  4858.     if (initTable(cacheEntry,FULL_REMAP) < 0)
  4859.     {
  4860.         msqlTrace(TRACE_OUT,"doSelect()");
  4861.         return(-1);
  4862.     }
  4863.  
  4864.     /*
  4865.     ** Tell the client how many fields there are in a row
  4866.     */
  4867.  
  4868.     if (dest == DEST_CLIENT)
  4869.     {
  4870.         sprintf(packet,"1:%d:\n",numFields);
  4871.         writePkt(outSock);
  4872.     }
  4873.  
  4874.  
  4875.     /*
  4876.     ** If the data is keyed and it's a simple condition just grab the row
  4877.     */
  4878.  
  4879.     useKey = 0;
  4880.     if (key)
  4881.     {
  4882.         if (key->op == EQ_OP)
  4883.         {
  4884.             useKey = 1;
  4885.             curCond = conds;
  4886.             while(curCond)
  4887.             {
  4888.                 if (curCond->bool == OR_BOOL)
  4889.                 {
  4890.                     useKey = 0;
  4891.                     break;
  4892.                 }
  4893.                 curCond = curCond->next;
  4894.             }
  4895.         }
  4896.     }
  4897.  
  4898.     if (useKey)
  4899.     {
  4900.         rowNum = readKey(cacheEntry,key);    
  4901.         msqlDebug(MOD_KEY,"Primary Key gave row %u\n",rowNum);
  4902.         if (rowNum != NO_POS)
  4903.         {
  4904.             row = readRow(cacheEntry,&active,rowNum);
  4905.             if (active)
  4906.             {
  4907.                 res = matchRow(cacheEntry,row,conds,clist);
  4908.                 if (res < 0)
  4909.                 {
  4910.                     return(-1);
  4911.                 }
  4912.                 if (res == 1)
  4913.                 {
  4914.                     extractValues(row,fields,flist);
  4915.                     if (dest == DEST_CLIENT)
  4916.                     {
  4917.                         bzero(packet,PKT_LEN);
  4918.                         formatPacket(packet,fields);
  4919.                         writePkt(outSock);
  4920.                     }
  4921.                     else
  4922.                     {
  4923.                         bzero((char*)(tmpTable->rowBuf
  4924.                             +1), tmpTable->rowLen);
  4925.                         fillRow(tmpTable->rowBuf + 1, 
  4926.                             fields, tmpFlist);
  4927.                         writeRow(tmpTable,NULL,NO_POS);
  4928.                     }
  4929.                 }
  4930.             }
  4931.         }
  4932.     }
  4933.     else
  4934.     {
  4935.         rowNum = 0;
  4936.         while((row = readRow(cacheEntry,&active,rowNum++) ))
  4937.         {
  4938.             if (!active)
  4939.                 continue;
  4940.             res = matchRow(cacheEntry,row,conds,clist);
  4941.             if (res < 0)
  4942.             {
  4943.                 return(-1);
  4944.             }
  4945.             if (res == 1)
  4946.             {
  4947.                 extractValues(row,fields,flist);
  4948.                 if (dest == DEST_CLIENT)
  4949.                 {
  4950.                     bzero(packet,PKT_LEN);
  4951.                     formatPacket(packet,fields);
  4952.                     writePkt(outSock);
  4953.                 }
  4954.                 else
  4955.                 {
  4956.                     bzero((char*)(tmpTable->rowBuf+1),
  4957.                             tmpTable->rowLen);
  4958.                     fillRow(tmpTable->rowBuf + 1, fields,
  4959.                         tmpFlist);
  4960.                     writeRow(tmpTable,NULL,NO_POS);
  4961.                 }
  4962.             }
  4963.         }
  4964.     }
  4965.     if (dest == DEST_CLIENT)
  4966.     {
  4967.         sprintf(packet,"-100:\n");
  4968.         writePkt(outSock);
  4969.  
  4970.         /*
  4971.         ** Send the field info down the line to the client
  4972.         */
  4973.         curField = fields;
  4974.         while(curField)
  4975.         {
  4976.             sprintf(outBuf,"%d",curField->length);
  4977.             sprintf(packet,"%d:%s%d:%s1:%d%d:%s1:%s1:%s", 
  4978.                 strlen(tables->name), tables->name,
  4979.                 strlen(curField->name), curField->name, 
  4980.                 curField->type,strlen(outBuf), outBuf, 
  4981.                 curField->flags & NOT_NULL_FLAG ? "Y":"N", 
  4982.                 curField->flags & PRI_KEY_FLAG ? "Y":"N");
  4983.             writePkt(outSock);
  4984.             curField = curField->next;
  4985.         }
  4986.         sprintf(packet,"-100:\n");
  4987.         writePkt(outSock);
  4988.     }
  4989.     msqlTrace(TRACE_OUT,"doSelect()");
  4990.     return(0);
  4991. }
  4992.  
  4993.  
  4994.  
  4995.  
  4996. extern    field_t    *fieldHead;
  4997.  
  4998. int msqlSelect(tables,fields,conds,order,DB)
  4999.     tname_t    *tables;
  5000.     field_t    *fields;
  5001.     cond_t    *conds;
  5002.     order_t    *order;
  5003.     char    *DB;
  5004. {
  5005.     cache_t    *cacheEntry,
  5006.         *table1,
  5007.         *table2,
  5008.         *tmpTable,
  5009.         *prevTable;
  5010.     REG    tname_t    *curTable;
  5011.     REG    field_t    *curField;
  5012.     int    join,
  5013.         foundTable;
  5014.  
  5015.     msqlTrace(TRACE_IN,"msqlSelect()");
  5016.  
  5017.     /*
  5018.     ** Check out the tables and fields specified in the query.  If
  5019.     ** multiple tables are specified all field specs must be
  5020.     ** qualified and they must reference a selected table.
  5021.     */
  5022.  
  5023.     curTable = tables;
  5024.     tmpTable = NULL;
  5025.     if (curTable->next)
  5026.     {
  5027.         join = 1;
  5028.     }
  5029.     else
  5030.     {
  5031.         cond_t    *curCond;
  5032.  
  5033.         /*
  5034.         ** If there's no joins ensure that each conditionand field
  5035.         ** is fully qualified with the correct table
  5036.         */
  5037.         qualifyFields(tables->name,fields);
  5038.         qualifyConds(tables->name,conds);
  5039.         qualifyOrder(tables->name,order);
  5040.         curField = fields;
  5041.         while(curField)
  5042.         {
  5043.             if (strcmp(curField->table,tables->name)!=0)
  5044.             {
  5045.                 sprintf(errMsg,UNSELECT_ERROR,curField->table);
  5046.                 return(-1);
  5047.             }
  5048.             curField = curField->next;
  5049.         }
  5050.         join = 0;
  5051.     }
  5052.  
  5053.     curField = fields;
  5054.     while (curField)
  5055.     {
  5056.         if (*(curField->table) == 0)
  5057.         {
  5058.             if (join)
  5059.             {
  5060.                 sprintf(errMsg, UNQUAL_JOIN_ERROR, 
  5061.                     curField->name);
  5062.                 return(-1);
  5063.             }
  5064.             curField = curField->next;
  5065.             continue;
  5066.         }
  5067.         curTable = tables;
  5068.         foundTable = 0;
  5069.         while(curTable)
  5070.         {
  5071.             if (strcmp(curTable->name,curField->table) == 0)
  5072.             {
  5073.                 foundTable = 1;
  5074.                 break;
  5075.             }
  5076.             curTable = curTable->next;
  5077.         }
  5078.         if (!foundTable)
  5079.         {
  5080.             sprintf(errMsg,UNSELECT_ERROR, curField->table);
  5081.             return(-1);
  5082.         }
  5083.         curField = curField->next;
  5084.     }
  5085.  
  5086.  
  5087.     /*
  5088.     ** If there's multiple tables, join the suckers.
  5089.     */
  5090.  
  5091.     if (join)
  5092.     {
  5093.         curTable = tables;
  5094.         while(curTable)
  5095.         {
  5096.             if (curTable == tables)
  5097.             {
  5098.                 table1 = loadTableDef(curTable->name,
  5099.                     curTable->cname,DB);
  5100.                 if (!table1)
  5101.                 {
  5102.                     msqlTrace(TRACE_OUT,"msqlSelect()");
  5103.                     return(-1);
  5104.                 }
  5105.                 if (initTable(table1,FULL_REMAP) < 0)
  5106.                 {
  5107.                     msqlTrace(TRACE_OUT,"msqlSelect()");
  5108.                     return(-1);
  5109.                 }
  5110.                 curTable = curTable->next;
  5111.                 table2 = loadTableDef(curTable->name,
  5112.                     curTable->cname,DB);
  5113.                 if (!table2)
  5114.                 {
  5115.                     msqlTrace(TRACE_OUT,"msqlSelect()");
  5116.                     return(-1);
  5117.                 }
  5118.                 if (initTable(table2,FULL_REMAP) < 0)
  5119.                 {
  5120.                     msqlTrace(TRACE_OUT,"msqlSelect()");
  5121.                     return(-1);
  5122.                 }
  5123.                 if (!table1 || !table2)
  5124.                 {
  5125.                     msqlTrace(TRACE_OUT,"msqlSelect()");
  5126.                     return(-1);
  5127.                 }
  5128.                 tmpTable = joinTables(table1,table2,conds,DB);
  5129.                 if (!tmpTable)
  5130.                 {
  5131.                     msqlTrace(TRACE_OUT,"msqlSelect()");
  5132.                     return(-1);
  5133.                 }
  5134.                     
  5135.             }
  5136.             else
  5137.             {
  5138.                 table1 = tmpTable;
  5139.                 table2 = loadTableDef(curTable->name,
  5140.                     curTable->cname,DB);
  5141.                 if (!table2)
  5142.                 {
  5143.                     msqlTrace(TRACE_OUT,"msqlSelect()");
  5144.                     return(-1);
  5145.                 }
  5146.                 if (initTable(table1,FULL_REMAP) < 0)
  5147.                 {
  5148.                     msqlTrace(TRACE_OUT,"msqlDelete()");
  5149.                     return(-1);
  5150.                 }
  5151.                 if (initTable(table2,FULL_REMAP) < 0)
  5152.                 {
  5153.                     msqlTrace(TRACE_OUT,"msqlDelete()");
  5154.                     return(-1);
  5155.                 }
  5156.                 tmpTable = joinTables(table1,table2,conds,DB);
  5157.                 if (table1->result)
  5158.                 {
  5159.                     freeTmpTable(table1);
  5160.                 }
  5161.                 if (!tmpTable)
  5162.                 {
  5163.                     return(-1);
  5164.                 }
  5165.             }
  5166.             curTable = curTable->next;
  5167.         }
  5168.     }
  5169.  
  5170.     /*
  5171.     ** Perform the actual select.  If there's an order clause or
  5172.     ** a pending DISTINCT, send the results to a table for further 
  5173.     ** processing.
  5174.     **
  5175.     ** Look for the wildcard field spec.  Must do this before we
  5176.     ** "setup" because it edits the field list.  selectWildcard
  5177.     ** is a global set from inside the yacc parser.  Wild card
  5178.     ** expansion is only called if this is set otherwise it will
  5179.     ** consume 50% of the execution time of selects!
  5180.     */
  5181.  
  5182.     if (!tmpTable)
  5183.     {
  5184.         if((cacheEntry = loadTableDef(tables->name,tables->cname,
  5185.             DB)) == NULL)
  5186.         {
  5187.             msqlTrace(TRACE_OUT,"msqlSelect()");
  5188.             return(-1);
  5189.         }
  5190.     }
  5191.     else
  5192.     {
  5193.         cacheEntry = tmpTable;
  5194.         /* conds = NULL; */
  5195.     }
  5196.     if (selectWildcard)
  5197.     {
  5198.         fields = expandFieldWildCards(cacheEntry,fields);
  5199.     }
  5200.  
  5201.     if (!order && !selectDistinct)
  5202.     {
  5203.         if (doSelect(cacheEntry,tables,fields,conds,
  5204.             DEST_CLIENT,NULL) < 0)
  5205.         {
  5206.             msqlTrace(TRACE_OUT,"msqlSelect()");
  5207.             return(-1);
  5208.         }
  5209.         if (cacheEntry->result)
  5210.         {
  5211.             freeTmpTable(cacheEntry);
  5212.         }
  5213.         msqlTrace(TRACE_OUT,"msqlSelect()");
  5214.         return(0);
  5215.     }
  5216.  
  5217.     /*
  5218.     ** From here on we just want a table with the required fields
  5219.     ** (i.e. not all the fields of a join)
  5220.     */
  5221.     tmpTable = createTmpTable(cacheEntry,NULL,fields);
  5222.     if (!tmpTable)
  5223.     {
  5224.         return(-1);
  5225.     }
  5226.     (void)sprintf(tmpTable->resInfo,"'%s (stripped %s)'",
  5227.         tmpTable->table,cacheEntry->table);
  5228.     if (doSelect(cacheEntry,tables,fields,conds,
  5229.         DEST_TABLE,tmpTable) < 0)
  5230.     {
  5231.         msqlTrace(TRACE_OUT,"msqlSelect()");
  5232.         return(-1);
  5233.     }
  5234.     if (cacheEntry->result)
  5235.     {
  5236.         freeTmpTable(cacheEntry);
  5237.     }
  5238.     cacheEntry = tmpTable;
  5239.  
  5240.     /*
  5241.     ** Blow away multiples if required
  5242.     */
  5243.     if (selectDistinct)
  5244.     {
  5245.         if (createDistinctTable(cacheEntry,NULL,fields) < 0)
  5246.         {
  5247.             msqlTrace(TRACE_OUT,"msqlSelect()");
  5248.             return(-1);
  5249.         }
  5250.     }
  5251.     
  5252.     /*
  5253.     ** Sort the result if required
  5254.     */
  5255.     if (order)
  5256.     {
  5257.         cache_t    *sortTable;
  5258.  
  5259.         sortTable = createSortedTable(cacheEntry,order);
  5260.  
  5261.         if (cacheEntry->result)
  5262.         {
  5263.             freeTmpTable(cacheEntry);
  5264.         }
  5265.         if (!sortTable)
  5266.         {
  5267.             msqlTrace(TRACE_OUT,"msqlSelect()");
  5268.             return(-1);
  5269.         }
  5270.         cacheEntry = sortTable;
  5271.     }
  5272.  
  5273.  
  5274.     /*
  5275.     ** Send the result to the client if we haven't yet.
  5276.     */
  5277.     if (doSelect(cacheEntry,tables,fields,conds,DEST_CLIENT,NULL)<0)
  5278.     {
  5279.         msqlTrace(TRACE_OUT,"msqlSelect()");
  5280.         return(-1);
  5281.     }
  5282.  
  5283.     /*
  5284.     ** Free the result table
  5285.     */
  5286.     if (cacheEntry->result)
  5287.     {
  5288.         freeTmpTable(cacheEntry);
  5289.     }
  5290.  
  5291.  
  5292.     msqlTrace(TRACE_OUT,"msqlSelect()");
  5293.     return(0);
  5294. }
  5295.  
  5296.  
  5297.  
  5298.  
  5299.  
  5300.  
  5301. void msqlCreateDB(sock,db)
  5302.     int    sock;
  5303.     char    *db;
  5304. {
  5305.     char    path[255];
  5306.     DIR    *dirp;
  5307.  
  5308.     /*
  5309.     ** See if the directory exists
  5310.     */
  5311.  
  5312.     (void)sprintf(path,"%s/msqldb/%s", msqlHomeDir, db);
  5313.     dirp = opendir(path);
  5314.     if (dirp)
  5315.     {
  5316.         closedir(dirp);
  5317.         sprintf(packet,"-1:Error creating database : %s exists!\n",db);
  5318.                 writePkt(sock);
  5319.         return;
  5320.     }
  5321.  
  5322.     /*
  5323.     ** Create the directory
  5324.     */
  5325.     if (mkdir(path,0700) < 0)
  5326.     {
  5327.         sprintf(packet,"-1:Error creating database\n");
  5328.         writePkt(sock);
  5329.         return;
  5330.     }
  5331.     sprintf(packet,"-100:\n");
  5332.     writePkt(sock);
  5333. }
  5334.  
  5335.  
  5336. void msqlDropDB(sock,db)
  5337.     int    sock;
  5338.     char    *db;
  5339. {
  5340.     char    path[255],
  5341.         filePath[255],
  5342.         buf[10];
  5343.     DIR    *dirp;
  5344. #ifdef HAVE_DIRENT
  5345.     struct    dirent *cur;
  5346. #else
  5347.     struct    direct *cur;
  5348. #endif
  5349.     int    index;
  5350.     cache_t    *entry;
  5351.  
  5352.     /*
  5353.     ** See if the directory exists
  5354.     */
  5355.  
  5356.     (void)sprintf(path,"%s/msqldb/%s", msqlHomeDir, db);
  5357.     dirp = opendir(path);
  5358.     if (!dirp)
  5359.     {
  5360.         sprintf(packet,"-1:Error dropping database : %s doesn't exist\n"
  5361.             , db);
  5362.         writePkt(sock);
  5363.         return;
  5364.     }
  5365.  
  5366.     /*
  5367.     ** Blow away any files but dodge '.' and '..'
  5368.     */
  5369.  
  5370.     cur = readdir(dirp);
  5371.     cur = readdir(dirp);
  5372.     cur = readdir(dirp);
  5373.     while(cur)
  5374.     {
  5375.         sprintf(filePath,"%s/%s",path,cur->d_name);
  5376.         unlink(filePath);
  5377.         cur = readdir(dirp);
  5378.     }
  5379.         
  5380.     if (rmdir(path) < 0)
  5381.     {
  5382.         sprintf(packet,"-1:Error dropping database\n");
  5383.         writePkt(sock);
  5384.         closedir(dirp);
  5385.         return;
  5386.     }
  5387.     closedir(dirp);
  5388.  
  5389.     /*
  5390.     ** Invalidate any cache entries that are for this DB
  5391.     */
  5392.     index = 0;
  5393.     while(index < CACHE_SIZE)
  5394.     {
  5395.         entry = tableCache + index++;
  5396.         if (strcmp(entry->DB,db) == 0)
  5397.         {
  5398.             freeTableDef(entry->def);
  5399.             entry->def = NULL;
  5400.             *(entry->DB) = 0;
  5401.             *(entry->table) = 0;
  5402.             entry->age = 0;
  5403.             safeFree(entry->rowBuf);
  5404.             safeFree(entry->keyBuf);
  5405.             close(entry->stackFD);
  5406.             close(entry->dataFD);
  5407.             close(entry->keyFD);
  5408. #ifdef HAVE_MMAP
  5409.             if (entry->dataMap != (caddr_t) NULL)
  5410.             {
  5411.                 munmap(entry->dataMap,entry->size);
  5412.                 entry->dataMap = NULL;
  5413.                 entry->size = 0;
  5414.             }
  5415.             if (entry->keyMap != (caddr_t) NULL)
  5416.             {
  5417.                 munmap(entry->keyMap,entry->keySize);
  5418.                 entry->keyMap = NULL;
  5419.                 entry->keySize = 0;
  5420.             }
  5421. #endif
  5422.         }
  5423.     }
  5424.     sprintf(packet,"-100:\n");
  5425.     writePkt(sock);
  5426. }
  5427.  
  5428.